1 /**
2  * @file resolve.h
3  * @author Michal Vasko <mvasko@cesnet.cz>
4  * @brief libyang resolve header
5  *
6  * Copyright (c) 2015 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 _RESOLVE_H
16 #define _RESOLVE_H
17 
18 #include "libyang.h"
19 #include "extensions.h"
20 
21 /**
22  * @brief Type of an unresolved item (in either SCHEMA or DATA)
23  */
24 enum UNRES_ITEM {
25     /* SCHEMA */
26     UNRES_USES = 0x00000001,          /* unresolved uses grouping (refines and augments in it are resolved as well) */
27     UNRES_IFFEAT = 0x00000002,        /* unresolved if-feature */
28     UNRES_TYPE_DER = 0x00000004,      /* unresolved derived type defined in leaf/leaflist */
29     UNRES_TYPE_DER_TPDF = 0x00000008, /* unresolved derived type defined as typedef */
30     UNRES_TYPE_DER_EXT = 0x00000010,
31     UNRES_TYPE_LEAFREF = 0x00000020,  /* check leafref value */
32     UNRES_AUGMENT = 0x00000040,       /* unresolved augment targets */
33     UNRES_CHOICE_DFLT = 0x00000080,   /* check choice default case */
34     UNRES_IDENT = 0x00000100,         /* unresolved derived identities */
35     UNRES_TYPE_IDENTREF = 0x00000200, /* check identityref value */
36     UNRES_FEATURE = 0x00000400,       /* feature for circular check, it must be postponed when all if-features are resolved */
37     UNRES_TYPEDEF_DFLT = 0x00000800,  /* validate default type value (from typedef) */
38     UNRES_TYPE_DFLT = 0x00001000,     /* validate default type value (from lys_node) */
39     UNRES_LIST_KEYS = 0x00002000,     /* list keys */
40     UNRES_LIST_UNIQ = 0x00004000,     /* list uniques */
41     UNRES_MOD_IMPLEMENT = 0x00008000, /* unimplemented module */
42     UNRES_EXT = 0x00010000,           /* extension instances */
43     UNRES_XPATH = 0x00020000,         /* unchecked XPath expression */
44     UNRES_EXT_FINALIZE = 0x00040000,  /* extension is already resolved, but needs to be finalized via plugin callbacks */
45 
46     /* DATA */
47     UNRES_LEAFREF = 0x00080000,       /* unresolved leafref reference */
48     UNRES_INSTID = 0x00100000,        /* unresolved instance-identifier reference */
49     UNRES_WHEN = 0x00200000,          /* unresolved when condition */
50     UNRES_MUST = 0x00400000,          /* unresolved must condition */
51     UNRES_MUST_INOUT = 0x00800000,    /* unresolved must condition in parent input or output */
52     UNRES_UNION = 0x01000000,         /* union with leafref which must be checked because the type can change without changing the
53                                          value itself, but removing the target node */
54     UNRES_UNIQ_LEAVES = 0x02000000,   /* list with a unique statement(s) whose leaves need to be checked */
55 
56     /* generic */
57     UNRES_RESOLVED = 0x04000000,      /* a resolved item */
58     UNRES_DELETE = 0x08000000,        /* prepared for auto-delete */
59 };
60 
61 /**
62  * @brief auxiliaty structure to hold all necessary information for UNRES_EXT
63  */
64 struct unres_ext {
65     union {
66         struct lyxml_elem *yin;         /**< YIN content of the extension instance */
67         struct yang_ext_substmt *yang;  /**< YANG content of strings */
68     } data;
69     LYS_INFORMAT datatype;              /**< type of the data in data union */
70 
71     /* data for lys_ext_instance structure */
72     void *parent;
73     struct lys_module *mod;
74     LYEXT_PAR parent_type;
75     LYEXT_SUBSTMT substmt;
76     uint8_t substmt_index;
77     uint8_t ext_index;
78 };
79 
80 /**
81  * @brief auxiliary structure to hold all necessary information for UNRES_LIST_UNIQ
82  */
83 struct unres_list_uniq {
84     struct lys_node *list;
85     const char *expr;
86     uint8_t *trg_type;
87 };
88 
89 /**
90  * @brief Unresolved items in DATA
91  */
92 struct unres_data {
93     struct lyd_node **node;
94     enum UNRES_ITEM *type;
95     uint32_t count;
96 
97     int store_diff;
98     struct lyd_difflist *diff;
99     unsigned int diff_size;
100     unsigned int diff_idx;
101 };
102 
103 /**
104  * @brief Unresolved items in a SCHEMA
105  */
106 struct unres_schema {
107     void **item;            /* array of pointers, each is determined by the type (one of lys_* structures) */
108     enum UNRES_ITEM *type;  /* array of unres types */
109     void **str_snode;       /* array of pointers, each is determined by the type (a string, a lys_node *, or NULL) */
110     struct lys_module **module; /* array of pointers to the item's module */
111     uint32_t count;         /* count of unres items */
112 };
113 
114 struct len_ran_intv {
115     /* 0 - unsigned, 1 - signed, 2 - floating point */
116     uint8_t kind;
117     union {
118         struct {
119             uint64_t min;
120             uint64_t max;
121         } uval;
122 
123         struct {
124             int64_t min;
125             int64_t max;
126         } sval;
127 
128         struct {
129             int64_t min;
130             int64_t max;
131         } fval;
132     } value;
133 
134     struct lys_type *type;     /* just to be able to get to optional error-message and/or error-app-tag */
135     struct len_ran_intv *next;
136 };
137 
138 /**
139  * @brief Convert a string with a decimal64 value into our representation.
140  * Syntax is expected to be correct. Does not log.
141  *
142  * @param[in,out] str_num Pointer to the beginning of the decimal64 number, returns the first unparsed character.
143  * @param[in] dig Fraction-digits of the resulting number.
144  * @param[out] num Decimal64 base value, fraction-digits equal \p dig.
145  * @return 0 on success, non-zero on error.
146  */
147 int parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num);
148 
149 unsigned int parse_identifier(const char *id);
150 
151 int parse_schema_nodeid(const char *id, const char **mod_name, int *mod_name_len, const char **name, int *nam_len,
152                         int *is_relative, int *has_predicate, int *all_desc, int extended);
153 
154 int parse_schema_json_predicate(const char *id, const char **mod_name, int *mod_name_len, const char **name,
155                                 int *nam_len, const char **value, int *val_len, int *has_predicate);
156 
157 /**
158  * @param[in] expr compiled if-feature expression
159  * @return 1 if enabled, 0 if disabled
160  */
161 int resolve_iffeature(struct lys_iffeature *expr);
162 void resolve_iffeature_getsizes(struct lys_iffeature *iffeat, unsigned int *expr_size, unsigned int *feat_size);
163 int resolve_iffeature_compile(struct lys_iffeature *iffeat_expr, const char *value, struct lys_node *node,
164                               int infeature, struct unres_schema *unres);
165 uint8_t iff_getop(uint8_t *list, int pos);
166 
167 int inherit_config_flag(struct lys_node *node, int flags, int clear);
168 
169 void resolve_identity_backlink_update(struct lys_ident *der, struct lys_ident *base);
170 
171 struct lyd_node *resolve_data_descendant_schema_nodeid(const char *nodeid, struct lyd_node *start);
172 
173 int resolve_schema_nodeid(const char *nodeid, const struct lys_node *start, const struct lys_module *cur_module,
174                           struct ly_set **ret, int extended, int no_node_error);
175 
176 int resolve_descendant_schema_nodeid(const char *nodeid, const struct lys_node *start, int ret_nodetype,
177                                      int no_innerlist, const struct lys_node **ret);
178 
179 int resolve_choice_default_schema_nodeid(const char *nodeid, const struct lys_node *start, const struct lys_node **ret);
180 
181 int resolve_absolute_schema_nodeid(const char *nodeid, const struct lys_module *module, int ret_nodetype,
182                                    const struct lys_node **ret);
183 
184 const struct lys_node *resolve_json_nodeid(const char *nodeid, const struct ly_ctx *ctx, const struct lys_node *start, int output);
185 
186 struct lyd_node *resolve_partial_json_data_nodeid(const char *nodeid, const char *llist_value, struct lyd_node *start,
187                                                   int options, int *parsed);
188 
189 int resolve_len_ran_interval(struct ly_ctx *ctx, const char *str_restr, struct lys_type *type, struct len_ran_intv **ret);
190 
191 int resolve_superior_type(const char *name, const char *prefix, const struct lys_module *module,
192                           const struct lys_node *parent, struct lys_tpdf **ret);
193 
194 int resolve_unique(struct lys_node *parent, const char *uniq_str_path, uint8_t *trg_type);
195 
196 void resolve_when_ctx_snode(const struct lys_node *schema, struct lys_node **ctx_snode,
197                             enum lyxp_node_type *ctx_snode_type);
198 
199 /* get know if resolve_when() is applicable to the node (there is when condition connected with this node)
200  *
201  * @param[in] mode 0 - search for when in parent until there is another possible data node
202  *                 2 - search for when until reached the stop node, if NULL, search in all parents
203  */
204 int resolve_applies_when(const struct lys_node *schema, int mode, const struct lys_node *stop);
205 
206 /* return: 0x0 - no applicable must,
207  *         0x1 - node's schema has must,
208  *         0x2 - node's parent is inout with must,
209  *         0x3 - 0x2 & 0x1 combined */
210 int resolve_applies_must(const struct lyd_node *node);
211 
212 struct lys_ident *resolve_identref(struct lys_type *type, const char *ident_name, struct lyd_node *node,
213                                    struct lys_module *mod, int dflt);
214 
215 int resolve_unres_schema(struct lys_module *mod, struct unres_schema *unres);
216 
217 int resolve_when(struct lyd_node *node, int ignore_fail, struct lys_when **failed_when);
218 
219 int unres_schema_add_str(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
220                          const char *str);
221 
222 int unres_schema_add_node(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
223                           struct lys_node *node);
224 
225 int unres_schema_dup(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type,
226                      void *new_item);
227 
228 /* start_on_backwards - unres is searched from the end to beginning, so the search will start
229  *                      on start_on_backwards index in unres (unless -1) and skip indices
230  *                      larger than start_on_backards
231  */
232 int unres_schema_find(struct unres_schema *unres, int start_on_backwards, void *item, enum UNRES_ITEM type);
233 
234 void unres_schema_free(struct lys_module *module, struct unres_schema **unres, int all);
235 
236 /**
237  * @brief Resolve instance-identifier in JSON data format. Logs directly.
238  *
239  * @param[in] data Data node where the path is used
240  * @param[in] path Instance-identifier node value.
241  * @param[in,out] ret Resolved instance or NULL.
242  *
243  * @return 0 on success (even if unresolved and \p ret is NULL), -1 on error.
244  */
245 int resolve_instid(struct lyd_node *data, const char *path, int req_inst, struct lyd_node **ret);
246 
247 int resolve_leafref(struct lyd_node_leaf_list *leaf, const char *path, int req_inst, struct lyd_node **ret);
248 
249 int resolve_union(struct lyd_node_leaf_list *leaf, struct lys_type *type, int store, int ignore_fail,
250                   struct lys_type **resolved_type);
251 
252 int resolve_unres_data_item(struct lyd_node *dnode, enum UNRES_ITEM type, int ignore_fail, int multi_error,
253         struct lys_when **failed_when);
254 
255 int unres_data_addonly(struct unres_data *unres, struct lyd_node *node, enum UNRES_ITEM type);
256 int unres_data_add(struct unres_data *unres, struct lyd_node *node, enum UNRES_ITEM type);
257 void unres_data_del(struct unres_data *unres, uint32_t i);
258 
259 int resolve_unres_data(struct ly_ctx *ctx, struct unres_data *unres, struct lyd_node **root, int options);
260 int schema_nodeid_siblingcheck(const struct lys_node *sibling, const struct lys_module *cur_module,
261                            const char *mod_name, int mod_name_len, const char *name, int nam_len);
262 
263 #endif /* _RESOLVE_H */
264