blob: 33199ca7541c3ba8c714b5bfda54110a05a2f09f [file] [log] [blame]
Radek Krejcid7e8a622018-10-29 15:54:55 +01001/**
Radek Krejci0935f412019-08-20 16:15:18 +02002 * @file plugins_exts.h
Radek Krejcid7e8a622018-10-29 15:54:55 +01003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskofbbea932022-06-07 11:00:55 +02004 * @author Michal Vasko <mvasko@cesnet.cz>
Radek Krejcid7e8a622018-10-29 15:54:55 +01005 * @brief libyang support for YANG extensions implementation.
6 *
Michal Vaskofbbea932022-06-07 11:00:55 +02007 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejcid7e8a622018-10-29 15:54:55 +01008 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
15
Radek Krejci0935f412019-08-20 16:15:18 +020016#ifndef LY_PLUGINS_EXTS_H_
17#define LY_PLUGINS_EXTS_H_
Radek Krejcid7e8a622018-10-29 15:54:55 +010018
Radek Krejci535ea9f2020-05-29 16:01:05 +020019#include "log.h"
Michal Vaskofbbea932022-06-07 11:00:55 +020020#include "parser_data.h"
Radek Krejci3e6632f2021-03-22 22:08:21 +010021#include "plugins.h"
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +010022#include "tree_data.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010023#include "tree_edit.h"
Radek Krejci0e59c312019-08-15 15:34:15 +020024#include "tree_schema.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020025
Radek Krejci5f9a3672021-03-05 21:35:22 +010026#include "plugins_exts_compile.h"
Radek Krejcif8d7f9a2021-03-10 14:32:36 +010027#include "plugins_exts_print.h"
Radek Krejci5f9a3672021-03-05 21:35:22 +010028
Radek Krejci535ea9f2020-05-29 16:01:05 +020029struct ly_ctx;
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +010030struct ly_in;
Radek Krejci535ea9f2020-05-29 16:01:05 +020031struct lyd_node;
Radek Krejci0aa1f702021-04-01 16:16:19 +020032struct lysc_ext_substmt;
Michal Vaskob4750962022-10-06 15:33:35 +020033struct lysp_ctx;
Radek Krejci0aa1f702021-04-01 16:16:19 +020034struct lysp_ext_instance;
Radek Krejci0e59c312019-08-15 15:34:15 +020035
Radek Krejcid7e8a622018-10-29 15:54:55 +010036#ifdef __cplusplus
37extern "C" {
38#endif
39
40/**
Radek Krejci75104122021-04-01 15:37:45 +020041 * @page howtoPluginsExtensions Extension Plugins
42 *
43 * Note that the part of the libyang API here is available only by including a separated `<libyang/plugins_exts.h>` header
44 * file. Also note that the extension plugins API is versioned separately from libyang itself, so backward incompatible
45 * changes can come even without changing libyang major version.
46 *
47 * YANG extensions are very complex. Usually only its description specifies how it is supposed to behave, what are the
48 * allowed substatements, their cardinality or if the standard YANG statements placed inside the extension differs somehow
aPiecekb0445f22021-06-24 11:34:07 +020049 * in their meaning or behavior. libyang provides the Extension plugins API to implement such extensions and add its support
Radek Krejci75104122021-04-01 15:37:45 +020050 * into libyang itself. However we tried our best, the API is not (and it cannot be) so universal and complete to cover all
51 * possibilities. There are definitely use cases which cannot be simply implemented only with this API.
52 *
53 * libyang implements 3 important extensions: [NACM](https://tools.ietf.org/html/rfc8341), [Metadata](@ref howtoDataMetadata)
54 * and [yang-data](@ref howtoDataYangdata). Despite the core implementation in all three cases is done via extension plugin
55 * API, also other parts of the libyang code had to be extended to cover complete scope of the extensions.
56 *
57 * We believe, that the API is capable to allow implementation of very wide range of YANG extensions. However, if you see
58 * limitations for the particular YANG extension, don't hesitate to contact the project developers to discuss all the
59 * options, including updating the API.
60 *
61 * The plugin's functionality is provided to libyang via a set of callbacks specified as an array of ::lyplg_ext_record
62 * structures using the ::LYPLG_EXTENSIONS macro.
63 *
64 * The most important ::lyplg_ext.compile callback is responsible for processing the parsed extension instance. In this
65 * phase, the callback must validate all the substatements, their values or placement of the extension instance itself.
66 * If needed, the processed data can be stored in some form into the compiled schema representation of the extension
67 * instance. To make the compilation process as easy as possible, libyang provides several
68 * [helper functions](@ref pluginsExtensionsCompile) to handle the schema compilation context and to compile standard YANG
69 * statements in the same way the libyang does it internally.
70 *
71 * The data validation callback ::lyplg_ext.validate is used for additional validation of a data nodes that contains the
72 * connected extension instance directly (as a substatement) or indirectly in case of terminal nodes via their type (no
73 * matter if the extension instance is placed directly in the leaf's/leaf-list's type or in the type of the referenced
74 * typedef).
75 *
76 * The ::lyplg_ext.sprinter callback implement printing the compiled extension instance data when the schema (module) is
77 * being printed in the ::LYS_OUT_YANG_COMPILED (info) format. As for compile callback, there are also
78 * [helper functions](@ref pluginsExtensionsPrint) to access printer's context and to print standard YANG statements
79 * placed in the extension instance by libyang itself.
80 *
81 * The last callback, ::lyplg_ext.free, is supposed to free all the data allocated by the ::lyplg_ext.compile callback.
82 * To free the data created by helper function ::lys_compile_extension_instance(), the plugin can used
83 * ::lyplg_ext_instance_substatements_free().
84 *
85 * The plugin information contains also the plugin identifier (::lyplg_type.id). This string can serve to identify the
86 * specific plugin responsible to storing data value. In case the user can recognize the id string, it can access the
87 * plugin specific data with the appropriate knowledge of its structure.
88 *
89 * Logging information from an extension plugin is possible via ::lyplg_ext_log() function
90 */
91
92/**
93 * @defgroup pluginsExtensions Plugins: Extensions
94 *
95 * Structures and functions to for libyang plugins implementing specific YANG extensions defined in YANG modules. For more
96 * information, see @ref howtoPluginsTypes.
97 *
98 * This part of libyang API is available by including `<libyang/plugins_ext.h>` header file.
Radek Krejcid7e8a622018-10-29 15:54:55 +010099 *
100 * @{
101 */
102
103/**
Radek Krejci0935f412019-08-20 16:15:18 +0200104 * @brief Extensions API version
105 */
Michal Vasko0b50f6b2022-10-05 15:07:55 +0200106#define LYPLG_EXT_API_VERSION 6
Radek Krejci0935f412019-08-20 16:15:18 +0200107
108/**
Michal Vaskob4750962022-10-06 15:33:35 +0200109 * @brief Generic test for operation statements.
110 *
111 * This macro matches a subset of schema nodes that maps to common ::lysc_node or ::lysp_node structures. To match all
112 * such nodes, use ::LY_STMT_IS_NODE()
113 *
114 * This macro matches action and RPC.
115 */
116#define LY_STMT_IS_OP(STMT) (((STMT) == LY_STMT_ACTION) || ((STMT) == LY_STMT_RPC))
117
118/**
119 * @brief Generic test for schema data nodes.
120 *
121 * This macro matches a subset of schema nodes that maps to common ::lysc_node or ::lysp_node structures. To match all
122 * such nodes, use ::LY_STMT_IS_NODE()
123 *
124 * This macro matches anydata, anyxml, case, choice, container, leaf, leaf-list, and list.
125 */
126#define LY_STMT_IS_DATA_NODE(STMT) (((STMT) == LY_STMT_ANYDATA) || ((STMT) == LY_STMT_ANYXML) || \
127 ((STMT) == LY_STMT_CASE) || ((STMT) == LY_STMT_CHOICE) || ((STMT) == LY_STMT_CONTAINER) || \
128 ((STMT) == LY_STMT_LEAF) || ((STMT) == LY_STMT_LEAF_LIST) || ((STMT) == LY_STMT_LIST))
129
130/**
131 * @brief Generic test for any schema node that maps to common ::lysc_node or ::lysp_node structures.
132 *
133 * Note that the list of statements that can appear in parsed or compiled schema trees differs (e.g. no uses in compiled tree).
134 *
135 * To check for some of the subsets of this test, try ::LY_STMT_IS_DATA_NODE() or ::LY_STMT_IS_OP().
136 *
137 * This macro matches action, anydata, anyxml, augment, case, choice, container, grouping, input, leaf, leaf-list, list,
138 * notification, output, RPC and uses.
139 */
140#define LY_STMT_IS_NODE(STMT) (((STMT) >= LY_STMT_NOTIFICATION) && ((STMT) <= LY_STMT_LIST))
141
142/**
143 * @brief List of YANG statements
144 */
145enum ly_stmt {
146 LY_STMT_NONE = 0,
147
148 LY_STMT_NOTIFICATION, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_notif *`.
149 The RPCs/Actions and Notifications are expected in a separated lists than the rest of
150 data definition nodes as it is done in generic structures of libyang. */
151 LY_STMT_INPUT,
152 LY_STMT_OUTPUT,
153 LY_STMT_ACTION, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_action *`.
154 The RPCs/Actions and Notifications are expected in a separated lists than the rest of
155 data definition nodes as it is done in generic structures of libyang. */
156 LY_STMT_RPC, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_action *`.
157 The RPCs/Actions and Notifications are expected in a separated lists than the rest of
158 data definition nodes as it is done in generic structures of libyang. */
159 LY_STMT_ANYDATA, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
160 Note that due to ::lysc_node compatibility the anydata is expected to be actually
161 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
162 Notifications are expected in a separated lists as it is done in generic structures
163 of libyang. */
164 LY_STMT_ANYXML, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
165 Note that due to ::lysc_node compatibility the anyxml is expected to be actually
166 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
167 Notifications are expected in a separated lists as it is done in generic structures
168 of libyang. */
169 LY_STMT_AUGMENT,
170 LY_STMT_CASE, /**< TODO is it possible to compile cases without the parent choice? */
171 LY_STMT_CHOICE, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
172 Note that due to ::lysc_node compatibility the choice is expected to be actually
173 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
174 Notifications are expected in a separated lists as it is done in generic structures
175 of libyang. */
176 LY_STMT_CONTAINER, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
177 Note that due to ::lysc_node compatibility the container is expected to be actually
178 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
179 Notifications are expected in a separated lists as it is done in generic structures
180 of libyang. */
181 LY_STMT_GROUPING,
182 LY_STMT_LEAF, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
183 Note that due to ::lysc_node compatibility the leaf is expected to be actually
184 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
185 Notifications are expected in a separated lists as it is done in generic structures
186 of libyang. */
187 LY_STMT_LEAF_LIST, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
188 Note that due to ::lysc_node compatibility the leaf-list is expected to be actually
189 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
190 Notifications are expected in a separated lists as it is done in generic structures
191 of libyang. */
192 LY_STMT_LIST, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
193 Note that due to ::lysc_node compatibility the list is expected to be actually
194 mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
195 Notifications are expected in a separated lists as it is done in generic structures
196 of libyang. */
197 LY_STMT_USES,
198
199 LY_STMT_ARGUMENT,
200 LY_STMT_BASE,
201 LY_STMT_BELONGS_TO,
202 LY_STMT_BIT,
203 LY_STMT_CONFIG, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
204 LY_STMT_CONTACT,
205 LY_STMT_DEFAULT,
206 LY_STMT_DESCRIPTION, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
207 or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
208 LY_STMT_DEVIATE,
209 LY_STMT_DEVIATION,
210 LY_STMT_ENUM,
211 LY_STMT_ERROR_APP_TAG,
212 LY_STMT_ERROR_MESSAGE,
213 LY_STMT_EXTENSION,
214 LY_STMT_EXTENSION_INSTANCE,
215 LY_STMT_FEATURE,
216 LY_STMT_FRACTION_DIGITS,
217 LY_STMT_IDENTITY,
218 LY_STMT_IF_FEATURE, /**< if-feature statements are not compiled, they are evaluated and the parent statement is
219 preserved only in case the evaluation of all the if-feature statements is true.
220 Therefore there is no storage expected. */
221 LY_STMT_IMPORT,
222 LY_STMT_INCLUDE,
223 LY_STMT_KEY,
224 LY_STMT_LENGTH,
225 LY_STMT_MANDATORY, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
226 LY_STMT_MAX_ELEMENTS,
227 LY_STMT_MIN_ELEMENTS,
228 LY_STMT_MODIFIER,
229 LY_STMT_MODULE,
230 LY_STMT_MUST,
231 LY_STMT_NAMESPACE,
232 LY_STMT_ORDERED_BY,
233 LY_STMT_ORGANIZATION,
234 LY_STMT_PATH,
235 LY_STMT_PATTERN,
236 LY_STMT_POSITION,
237 LY_STMT_PREFIX,
238 LY_STMT_PRESENCE,
239 LY_STMT_RANGE,
240 LY_STMT_REFERENCE, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
241 or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
242 LY_STMT_REFINE,
243 LY_STMT_REQUIRE_INSTANCE,
244 LY_STMT_REVISION,
245 LY_STMT_REVISION_DATE,
246 LY_STMT_STATUS, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
247 LY_STMT_SUBMODULE,
248 LY_STMT_TYPE, /**< in ::lysc_ext_substmt.storage stored as a pointer to `struct lysc_type *` (cardinality < #LY_STMT_CARD_SOME)
249 or as a pointer to a [sized array](@ref sizedarrays) `struct lysc_type **` */
250 LY_STMT_TYPEDEF,
251 LY_STMT_UNIQUE,
252 LY_STMT_UNITS, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
253 or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
254 LY_STMT_VALUE,
255 LY_STMT_WHEN,
256 LY_STMT_YANG_VERSION,
257 LY_STMT_YIN_ELEMENT,
258
259 /* separated from the list of statements
260 * the following tokens are part of the syntax and parsers have to work
261 * with them, but they are not a standard YANG statements
262 */
263 LY_STMT_SYNTAX_SEMICOLON,
264 LY_STMT_SYNTAX_LEFT_BRACE,
265 LY_STMT_SYNTAX_RIGHT_BRACE,
266
267 /*
268 * YIN-specific tokens, still they are part of the syntax, but not the standard statements
269 */
270 LY_STMT_ARG_TEXT,
271 LY_STMT_ARG_VALUE
272};
273
274/**
275 * @brief Possible cardinalities of the YANG statements.
276 *
277 * Used in extensions plugins to define cardinalities of the extension instance substatements.
278 */
279enum ly_stmt_cardinality {
280 LY_STMT_CARD_OPT, /* 0..1 */
281 LY_STMT_CARD_MAND, /* 1 */
282 LY_STMT_CARD_SOME, /* 1..n */
283 LY_STMT_CARD_ANY /* 0..n */
284};
285
286/**
287 * @brief Helper structure for generic storage of the extension instances content.
288 */
289struct lysp_stmt {
290 const char *stmt; /**< identifier of the statement */
291 const char *arg; /**< statement's argument */
292 LY_VALUE_FORMAT format; /**< prefix format of the identifier/argument (::LY_VALUE_XML is YIN format) */
293 void *prefix_data; /**< Format-specific data for prefix resolution (see ly_resolve_prefix()) */
294
295 struct lysp_stmt *next; /**< link to the next statement */
296 struct lysp_stmt *child; /**< list of the statement's substatements (linked list) */
297 uint16_t flags; /**< statement flags, can be set to LYS_YIN_ATTR */
298 enum ly_stmt kw; /**< numeric respresentation of the stmt value */
299};
300
301/**
302 * @brief YANG extension instance
303 */
304struct lysp_ext_instance {
305 const char *name; /**< extension identifier, including possible prefix */
306 const char *argument; /**< optional value of the extension's argument */
307 LY_VALUE_FORMAT format; /**< prefix format of the extension name/argument (::LY_VALUE_XML is YIN format) */
308 struct lysp_node *parsed; /**< Simply parsed (unresolved) YANG schema tree serving as a cache.
309 Only ::lys_compile_extension_instance() can set this. */
310 void *prefix_data; /**< Format-specific data for prefix resolution
311 (see ly_resolve_prefix()) */
312
313 struct lysp_stmt *child; /**< list of the extension's substatements (linked list) */
314
315 void *parent; /**< pointer to the parent element holding the extension instance(s), use
316 ::lysp_ext_instance#parent_stmt to access the schema element */
317 enum ly_stmt parent_stmt; /**< value identifying placement of the extension instance */
318 LY_ARRAY_COUNT_TYPE parent_stmt_index; /**< in case the instance is in a substatement, this identifies
319 the index of that substatement in its [sized array](@ref sizedarrays) (if any) */
320 uint16_t flags; /**< LYS_INTERNAL value (@ref snodeflags) */
321 const struct lyplg_ext_record *record; /**< extension defintion plugin record, if any */
322};
323
324/**
325 * @brief Description of the extension instance substatements.
326 *
327 * Provided by extensions plugins to libyang to be able to correctly compile the content of extension instances.
328 * Note that order of the defined records matters - just follow the values of ::ly_stmt and order the records from lower to higher values.
329 */
330struct lysc_ext_substmt {
331 enum ly_stmt stmt; /**< allowed substatement */
332 enum ly_stmt_cardinality cardinality; /**< cardinality of the substatement */
333 void *storage; /**< pointer to the storage of the compiled statement according to the specific
334 lysc_ext_substmt::stmt and lysc_ext_substmt::cardinality */
335};
336
337/**
338 * @brief YANG extension instance
339 */
340struct lysc_ext_instance {
341 struct lysc_ext *def; /**< pointer to the extension definition */
342 const char *argument; /**< optional value of the extension's argument */
343 struct lys_module *module; /**< module where the extension instantiated is defined */
344 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
345 struct lysc_ext_substmt *substmts; /**< list of allowed substatements with the storage to access the present
346 substatements ([sized array](@ref sizedarrays)) */
347 void *data; /**< private plugins's data, not used by libyang */
348
349 void *parent; /**< pointer to the parent element holding the extension instance(s), use
350 ::lysc_ext_instance#parent_stmt to access the schema element */
351 enum ly_stmt parent_stmt; /**< value identifying placement of the extension instance in specific statement */
352 LY_ARRAY_COUNT_TYPE parent_stmt_index; /**< in case the instance is in a substatement, this identifies
353 the index of that substatement in its [sized array](@ref sizedarrays) (if any) */
354};
355
356/**
Radek Krejcia6f61e72021-03-24 21:00:19 +0100357 * @brief Macro to define plugin information in external plugins
358 *
359 * Use as follows:
360 * LYPLG_EXTENSIONS = {{<filled information of ::lyplg_ext_record>}, ..., {0}};
Radek Krejci0935f412019-08-20 16:15:18 +0200361 */
Radek Krejcia6f61e72021-03-24 21:00:19 +0100362#define LYPLG_EXTENSIONS \
363 uint32_t plugins_extensions_apiver__ = LYPLG_EXT_API_VERSION; \
364 const struct lyplg_ext_record plugins_extensions__[]
Radek Krejci0935f412019-08-20 16:15:18 +0200365
Radek Krejci38d85362019-09-05 16:26:38 +0200366
367/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200368 * @brief Callback to compile extension from the lysp_ext_instance to the lysc_ext_instance. The later structure is generally prepared
369 * and only the extension specific data are supposed to be added (if any).
370 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100371 * The parsed generic statements can be processed by the callback on its own or the ::lys_compile_extension_instance
372 * function can be used to let the compilation to libyang following the standard rules for processing the YANG statements.
373 *
Radek Krejci0e59c312019-08-15 15:34:15 +0200374 * @param[in] cctx Current compile context.
375 * @param[in] p_ext Parsed extension instance data.
Michal Vaskoddd76592022-01-17 13:34:48 +0100376 * @param[in,out] c_ext Prepared compiled extension instance structure where an addition, extension-specific, data are
377 * supposed to be placed for later use (data validation or use of external tool).
Radek Krejci0e59c312019-08-15 15:34:15 +0200378 * @return LY_SUCCESS in case of success.
379 * @return LY_EVALID in case of non-conforming parsed data.
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100380 * @return LY_ENOT in case the extension instance is not supported and should be removed.
Radek Krejci0e59c312019-08-15 15:34:15 +0200381 */
Michal Vaskoddd76592022-01-17 13:34:48 +0100382typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext,
383 struct lysc_ext_instance *c_ext);
Radek Krejci0e59c312019-08-15 15:34:15 +0200384
385/**
Michal Vaskoddd76592022-01-17 13:34:48 +0100386 * @brief Callback to print the compiled extension instance's private data in the INFO format.
387 *
388 * @param[in] ctx YANG printer context to provide output handler and other information for printing.
389 * @param[in] ext The compiled extension instance, mainly to access the extensions.
390 * @param[in,out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
391 * 1 otherwise.
392 * @return LY_SUCCESS when everything was fine, other LY_ERR values in case of failure
393 */
394typedef LY_ERR (*lyplg_ext_schema_printer_clb)(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag);
395
396/**
397 * @brief Callback to free the extension-specific data created by its compilation.
Radek Krejci0e59c312019-08-15 15:34:15 +0200398 *
Radek Krejci38d85362019-09-05 16:26:38 +0200399 * @param[in] ctx libyang context.
Radek Krejci0e59c312019-08-15 15:34:15 +0200400 * @param[in,out] ext Compiled extension structure where the data to free are placed.
401 */
Radek Krejci0b013302021-03-29 15:22:32 +0200402typedef void (*lyplg_ext_free_clb)(struct ly_ctx *ctx, struct lysc_ext_instance *ext);
Radek Krejci0e59c312019-08-15 15:34:15 +0200403
404/**
Michal Vasko135719f2022-08-25 12:18:17 +0200405 * @brief Callback called for all data nodes connected to the extension instance.
406 *
407 * Can be used for additional data node validation. Is called only after the whole data tree is created and standard
Michal Vaskoeba23112022-08-26 08:35:41 +0200408 * validation succeeds. Not called when parsing data and ::LYD_PARSE_ONLY is used.
Michal Vasko135719f2022-08-25 12:18:17 +0200409 *
410 * @param[in] ext Compiled extension instance.
411 * @param[in] node Data node to process.
Michal Vaskoeba23112022-08-26 08:35:41 +0200412 * @param[in] validate_options Options used for the validation phase, see @ref datavalidationoptions.
Michal Vasko135719f2022-08-25 12:18:17 +0200413 * @return LY_SUCCESS on success.
414 * @return LY_ERR on error.
415 */
Michal Vaskoeba23112022-08-26 08:35:41 +0200416typedef LY_ERR (*lyplg_ext_data_node_clb)(struct lysc_ext_instance *ext, struct lyd_node *node, uint32_t validate_options);
Michal Vasko135719f2022-08-25 12:18:17 +0200417
418/**
Michal Vasko8cc3f662022-03-29 11:25:51 +0200419 * @brief Callback for getting a schema node for a new YANG instance data described by an extension instance.
420 * Needed only if the extension instance supports some nested standard YANG data.
Radek Krejci0e59c312019-08-15 15:34:15 +0200421 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100422 * @param[in] ext Compiled extension instance.
Michal Vasko8cc3f662022-03-29 11:25:51 +0200423 * @param[in] parent Parsed parent data node. Set if @p sparent is NULL.
424 * @param[in] sparent Schema parent node. Set if @p parent is NULL.
425 * @param[in] prefix Element prefix, if any.
426 * @param[in] prefix_len Length of @p prefix.
427 * @param[in] format Format of @p prefix.
428 * @param[in] prefix_data Format-specific prefix data.
429 * @param[in] name Element name.
430 * @param[in] name_len Length of @p name.
431 * @param[out] snode Schema node to use for parsing the node.
Michal Vaskoddd76592022-01-17 13:34:48 +0100432 * @return LY_SUCCESS on success.
433 * @return LY_ENOT if the data are not described by @p ext.
434 * @return LY_ERR on error.
Radek Krejci0e59c312019-08-15 15:34:15 +0200435 */
Michal Vasko8cc3f662022-03-29 11:25:51 +0200436typedef LY_ERR (*lyplg_ext_data_snode_clb)(struct lysc_ext_instance *ext, const struct lyd_node *parent,
437 const struct lysc_node *sparent, const char *prefix, size_t prefix_len, LY_VALUE_FORMAT format, void *prefix_data,
438 const char *name, size_t name_len, const struct lysc_node **snode);
Radek Krejci0e59c312019-08-15 15:34:15 +0200439
440/**
Michal Vaskoddd76592022-01-17 13:34:48 +0100441 * @brief Callback for validating parsed YANG instance data described by an extension instance.
Radek Krejciadcf63d2021-02-09 10:21:18 +0100442 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100443 * This callback is used only for nested data definition (with a standard YANG schema parent).
Radek Krejciadcf63d2021-02-09 10:21:18 +0100444 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100445 * @param[in] ext Compiled extension instance.
Michal Vasko9af7cd42022-04-05 12:26:09 +0200446 * @param[in] sibling First sibling with schema node returned by ::lyplg_ext_data_snode_clb.
Michal Vaskofbbea932022-06-07 11:00:55 +0200447 * @param[in] dep_tree Tree to be used for validating references from the operation subtree, if operation.
448 * @param[in] data_type Validated data type, can be ::LYD_TYPE_DATA_YANG, ::LYD_TYPE_RPC_YANG, ::LYD_TYPE_NOTIF_YANG,
449 * or ::LYD_TYPE_REPLY_YANG.
Michal Vaskoddd76592022-01-17 13:34:48 +0100450 * @param[in] val_opts Validation options, see @ref datavalidationoptions.
Michal Vaskof4c6f002022-04-01 09:12:22 +0200451 * @param[out] diff Optional diff with any changes made by the validation.
Michal Vaskoddd76592022-01-17 13:34:48 +0100452 * @return LY_SUCCESS on success.
453 * @return LY_ERR on error.
Radek Krejciadcf63d2021-02-09 10:21:18 +0100454 */
Michal Vaskofbbea932022-06-07 11:00:55 +0200455typedef LY_ERR (*lyplg_ext_data_validate_clb)(struct lysc_ext_instance *ext, struct lyd_node *sibling,
456 const struct lyd_node *dep_tree, enum lyd_type data_type, uint32_t val_opts, struct lyd_node **diff);
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100457
458/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200459 * @brief Extension plugin implementing various aspects of a YANG extension
460 */
Radek Krejcicc9e30f2021-03-29 12:45:08 +0200461struct lyplg_ext {
Michal Vaskoddd76592022-01-17 13:34:48 +0100462 const char *id; /**< plugin identification (mainly for distinguish incompatible versions
463 of the plugins for external tools) */
464 lyplg_ext_compile_clb compile; /**< callback to compile extension instance from the parsed data */
465 lyplg_ext_schema_printer_clb sprinter; /**< callback to print the compiled content (info format) of the extension
466 instance */
467 lyplg_ext_free_clb free; /**< free the extension-specific data created by its compilation */
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100468
Michal Vasko135719f2022-08-25 12:18:17 +0200469 lyplg_ext_data_node_clb node; /**< callback to validate most relevant data instance for the extension
470 instance */
Michal Vasko8cc3f662022-03-29 11:25:51 +0200471 lyplg_ext_data_snode_clb snode; /**< callback to get schema node for nested YANG data */
Michal Vaskoddd76592022-01-17 13:34:48 +0100472 lyplg_ext_data_validate_clb validate; /**< callback to validate parsed data instances according to the extension
473 definition */
Radek Krejci0e59c312019-08-15 15:34:15 +0200474};
475
Radek Krejci3e6632f2021-03-22 22:08:21 +0100476struct lyplg_ext_record {
477 /* plugin identification */
478 const char *module; /**< name of the module where the extension is defined */
479 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
480 which is not an optimal approach due to a possible future revisions of the module.
481 Instead, there should be defined multiple items in the plugins list, each with the
482 different revision, but all with the same pointer to the plugin functions. The
483 only valid use case for the NULL revision is the case the module has no revision. */
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100484 const char *name; /**< YANG name of the extension */
Radek Krejci3e6632f2021-03-22 22:08:21 +0100485
486 /* runtime data */
487 struct lyplg_ext plugin; /**< data to utilize plugin implementation */
488};
489
Michal Vasko61ad1ff2022-02-10 15:48:39 +0100490/**
Michal Vaskob4750962022-10-06 15:33:35 +0200491 * @brief Stringify statement identifier.
492 *
493 * @param[in] stmt The statement identifier to stringify.
494 * @return Constant string representation of the given @p stmt.
495 */
496LIBYANG_API_DECL const char *ly_stmt2str(enum ly_stmt stmt);
497
498/**
499 * @brief Stringify statement cardinality.
500 *
501 * @param[in] card The cardinality to stringify.
502 * @return Constant string representation of the given @p card.
503 */
504LIBYANG_API_DECL const char *ly_cardinality2str(enum ly_stmt_cardinality card);
505
506/**
507 * @brief Convert nodetype to statement identifier
508 *
509 * @param[in] nodetype Nodetype to convert.
510 * @return Statement identifier representing the given @p nodetype.
511 */
512LIBYANG_API_DECL enum ly_stmt lys_nodetype2stmt(uint16_t nodetype);
513
514/**
515 * @brief Free the extension instance's data compiled with ::lys_compile_extension_instance().
516 *
517 * @param[in] ctx libyang context
518 * @param[in] substmts The sized array of extension instance's substatements. The whole array is freed except the storage
519 * places which are expected to be covered by the extension plugin.
520 */
521LIBYANG_API_DECL void lyplg_ext_instance_substatements_free(struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
522
523/**
Michal Vasko61ad1ff2022-02-10 15:48:39 +0100524 * @brief Get specific run-time extension instance data from a callback set by ::ly_ctx_set_ext_data_clb().
525 *
526 * @param[in] ctx Context with the callback.
527 * @param[in] ext Compiled extension instance.
528 * @param[out] ext_data Provided extension instance data.
529 * @param[out] ext_data_free Whether the extension instance should free @p ext_data or not.
530 * @return LY_SUCCESS on success.
531 * @return LY_ERR on error.
532 */
Michal Vaskoddd76592022-01-17 13:34:48 +0100533LIBYANG_API_DECL LY_ERR lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data,
534 ly_bool *ext_data_free);
535
536/**
537 * @brief Insert extension instance data into a parent.
538 *
539 * @param[in] parent Parent node to insert into.
540 * @param[in] first First top-level sibling node to insert.
541 * @return LY_SUCCESS on success.
542 * @return LY_ERR error on error.
543 */
544LIBYANG_API_DECL LY_ERR lyd_insert_ext(struct lyd_node *parent, struct lyd_node *first);
545
Radek Krejci0935f412019-08-20 16:15:18 +0200546/**
547 * @brief Provide a log message from an extension plugin.
548 *
549 * @param[in] ext Compiled extension structure providing generic information about the extension/plugin causing the message.
550 * @param[in] level Log message level (error, warning, etc.)
551 * @param[in] err_no Error type code.
552 * @param[in] path Path relevant to the message.
553 * @param[in] format Format string to print.
554 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100555LIBYANG_API_DECL void lyplg_ext_log(const struct lysc_ext_instance *ext, LY_LOG_LEVEL level, LY_ERR err_no, const char *path,
Radek Krejci0b013302021-03-29 15:22:32 +0200556 const char *format, ...);
Radek Krejci0935f412019-08-20 16:15:18 +0200557
ekinzie0ab8b302022-10-10 03:03:57 -0400558/**
559 * @brief Expand parent-reference xpath expressions
560 *
561 * @param ext[in] context allocated for extension
562 * @param refs[out] set of lysc nodes matching parent-refernce xpaths
563 * @return LY_ERR value.
564 */
565LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struct ly_set **refs);
566
567/**
568 * @brief Allocate a new context for a particular instance of the
569 * yangmnt:mount-point extension. Caller is responsible for destroying
570 * the resulting context.
571 *
572 * @param[in] ext Compiled extension instance.
573 * @param[out] ctx A context with modules loaded from the list found in
574 * the extension data.
575 * @return LY_ERR value.
576 */
577LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struct ly_ctx **ctx);
578
Michal Vaskob4750962022-10-06 15:33:35 +0200579/**
580 * @brief Get pointer to the storage of the specified substatement in the given extension instance.
581 *
582 * The function simplifies access into the ::lysc_ext_instance.substmts sized array.
583 *
584 * @param[in] ext Compiled extension instance to process.
585 * @param[in] substmt Extension substatement to search for.
586 * @param[out] instance_p Pointer where the storage of the @p substmt will be provided. The specific type returned depends
587 * on the @p substmt and can be found in the documentation of each ::ly_stmt value. Also note that some of the substatements
588 * (::lysc_node based or flags) can share the storage with other substatements. In case the pointer is NULL, still the return
589 * code can be used to at least know if the substatement is allowed for the extension.
590 * @param[out] cardinality_p Pointer to provide allowed cardinality of the substatements in the extension. Note that in some
591 * cases, the type of the storage depends also on the cardinality of the substatement.
592 * @return LY_SUCCESS if the @p substmt found.
593 * @return LY_ENOT in case the @p ext is not able to store (does not allow) the specified @p substmt.
594 */
595LIBYANG_API_DECL LY_ERR lysc_ext_substmt(const struct lysc_ext_instance *ext, enum ly_stmt substmt,
596 void **instance_p, enum ly_stmt_cardinality *cardinality_p);
597
Radek Krejci75104122021-04-01 15:37:45 +0200598/** @} pluginsExtensions */
Radek Krejcid7e8a622018-10-29 15:54:55 +0100599
600#ifdef __cplusplus
601}
602#endif
603
Radek Krejci0935f412019-08-20 16:15:18 +0200604#endif /* LY_PLUGINS_EXTS_H_ */