1 /*
2  *
3   ***** BEGIN LICENSE BLOCK *****
4 
5   Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
6   Copyright (C) 2017-2019 Olof Hagsand
7   Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
8 
9   This file is part of CLIXON.
10 
11   Licensed under the Apache License, Version 2.0 (the "License");
12   you may not use this file except in compliance with the License.
13   You may obtain a copy of the License at
14 
15     http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22 
23   Alternatively, the contents of this file may be used under the terms of
24   the GNU General Public License Version 3 or later (the "GPL"),
25   in which case the provisions of the GPL are applicable instead
26   of those above. If you wish to allow use of your version of this file only
27   under the terms of the GPL, and not to allow others to
28   use your version of this file under the terms of Apache License version 2,
29   indicate your decision by deleting the provisions above and replace them with
30   the  notice and other provisions required by the GPL. If you do not delete
31   the provisions above, a recipient may use your version of this file under
32   the terms of any one of the Apache License version 2 or the GPL.
33 
34   ***** END LICENSE BLOCK *****
35 
36  * Clixon XML object (cxobj) support functions.
37  * @see https://www.w3.org/TR/2008/REC-xml-20081126
38  *      https://www.w3.org/TR/2009/REC-xml-names-20091208/
39  * Canonical XML version (just for info)
40  *      https://www.w3.org/TR/xml-c14n
41  */
42 #ifndef _CLIXON_XML_H
43 #define _CLIXON_XML_H
44 
45 /*
46  * Constants
47  */
48 
49 /* Default NETCONF namespace (see rfc6241 3.1)
50  * See USE_NETCONF_NS_AS_DEFAULT for use of this namespace as default
51  * Also, bind it to prefix:nc as used by, for example, the operation attribute
52  */
53 #define NETCONF_BASE_NAMESPACE "urn:ietf:params:xml:ns:netconf:base:1.0"
54 #define NETCONF_BASE_PREFIX "nc"
55 
56 /* See RFC 7950 Sec 5.3.1: YANG defines an XML namespace for NETCONF <edit-config>
57  * operations, <error-info> content, and the <action> element.
58  */
59 #define YANG_XML_NAMESPACE "urn:ietf:params:xml:ns:yang:1"
60 /*
61  * Types
62  */
63 /* Netconf operation type */
64 enum operation_type{ /* edit-config operation */
65     OP_MERGE,  /* merge config-data */
66     OP_REPLACE,/* replace or create config-data */
67     OP_CREATE, /* create config data, error if exist */
68     OP_DELETE, /* delete config data, error if it does not exist */
69     OP_REMOVE, /* delete config data (not a netconf feature) */
70     OP_NONE
71 };
72 
73 /* Netconf insert type (see RFC7950 Sec 7.8.6) */
74 enum insert_type{ /* edit-config insert */
75     INS_FIRST,
76     INS_LAST,
77     INS_BEFORE,
78     INS_AFTER,
79 };
80 
81 /* XML object types */
82 enum cxobj_type {CX_ERROR=-1,
83 		 CX_ELMNT,
84 		 CX_ATTR,
85 		 CX_BODY};
86 
87 /* How to bind yang to XML top-level when parsing
88  * Assume an XML tree x with parent xp (or NULL) and a set of children c1,c2:
89  *
90  *                (XML)  xp
91  *                       |
92  *                       x
93  *                      / \
94  *                     c1  c2
95  * (1) If you make a binding using YB_MODULE, you assume there is a loaded module "ym" with a top-level
96  * data resource "y" that the XML node x can match to:
97  *
98  *                (XML)  xp          ym (YANG)
99  *                       |           |
100  *                       x - - - - - y
101  *                      / \         / \
102  *                     x1  x2 - -  y1  y2
103  * In that case, "y" is a container, list, leaf or leaf-list with same name as "x".
104  *
105  * (2) If you make a binding using YB_PARENT, you assume xp already have a YANG binding (eg to "yp"):
106  *
107  *                (XML)  xp - - - -  yp (YANG)
108  *                       |
109  *                       x
110  * so that the yang binding of "x" is a child of "yp":
111  *
112  *                (XML)  xp - - - -  yp (YANG)
113  *                       |           |
114  *                       x  - - - -  y
115  *                      / \         / \
116  *                     x1  x2 - -  y1  y2
117  */
118 enum yang_bind{
119     YB_NONE=0,   /* Dont do Yang binding */
120     YB_MODULE,   /* Search for matching yang binding among top-level symbols of Yang modules */
121     YB_PARENT,   /* Assume yang binding of existing parent and match its children by name */
122     YB_RPC,      /* Assume top-level xml is an netconf RPC message (or hello) */
123 
124 };
125 typedef enum yang_bind yang_bind;
126 
127 #define CX_ANY CX_ERROR /* catch all and error is same */
128 
129 typedef struct xml cxobj; /* struct defined in clicon_xml.c */
130 
131 /*! Callback function type for xml_apply
132  * @retval    -1    Error, aborted at first error encounter
133  * @retval     0    OK, continue
134  * @retval     1    Abort, dont continue with others
135  * @retval     2    Locally, just abort this subtree, continue with others
136  */
137 typedef int (xml_applyfn_t)(cxobj *x, void *arg);
138 
139 typedef struct clixon_xml_vec clixon_xvec; /* struct defined in clicon_xml_vec.c */
140 
141 /*
142  * xml_flag() flags:
143  */
144 #define XML_FLAG_MARK    0x01  /* Marker for dynamic algorithms, eg expand */
145 #define XML_FLAG_ADD     0x02  /* Node is added (commits) or parent added rec*/
146 #define XML_FLAG_DEL     0x04  /* Node is deleted (commits) or parent deleted rec */
147 #define XML_FLAG_CHANGE  0x08  /* Node is changed (commits) or child changed rec */
148 #define XML_FLAG_NONE    0x10  /* Node is added as NONE */
149 #define XML_FLAG_DEFAULT 0x20  /* Added when a value is set as default @see xml_default */
150 
151 /*
152  * Prototypes
153  */
154 char     *xml_type2str(enum cxobj_type type);
155 int       xml_stats_global(uint64_t *nr);
156 int       xml_stats(cxobj *xt, uint64_t *nrp, size_t *szp);
157 char     *xml_name(cxobj *xn);
158 int       xml_name_set(cxobj *xn, char *name);
159 char     *xml_prefix(cxobj *xn);
160 int       xml_prefix_set(cxobj *xn, char *name);
161 char     *nscache_get(cxobj *x, char *prefix);
162 int       nscache_get_prefix(cxobj *x, char *ns, char **prefix);
163 cvec     *nscache_get_all(cxobj *x);
164 int       nscache_set(cxobj *x,	char *prefix, char *ns);
165 int       nscache_clear(cxobj *x);
166 int       nscache_replace(cxobj *x, cvec *ns);
167 
168 int       xmlns_set(cxobj *x, char *prefix, char *ns);
169 cxobj    *xml_parent(cxobj *xn);
170 int       xml_parent_set(cxobj *xn, cxobj *parent);
171 
172 uint16_t  xml_flag(cxobj *xn, uint16_t flag);
173 int       xml_flag_set(cxobj *xn, uint16_t flag);
174 int       xml_flag_reset(cxobj *xn, uint16_t flag);
175 
176 char     *xml_value(cxobj *xn);
177 int       xml_value_set(cxobj *xn, char *val);
178 int       xml_value_append(cxobj *xn, char *val);
179 enum cxobj_type xml_type(cxobj *xn);
180 
181 int       xml_child_nr(cxobj *xn);
182 int       xml_child_nr_type(cxobj *xn, enum cxobj_type type);
183 int       xml_child_nr_notype(cxobj *xn, enum cxobj_type type);
184 cxobj    *xml_child_i(cxobj *xn, int i);
185 cxobj    *xml_child_i_type(cxobj *xn, int i, enum cxobj_type type);
186 cxobj    *xml_child_i_set(cxobj *xt, int i, cxobj *xc);
187 int       xml_child_order(cxobj *xn, cxobj *xc);
188 cxobj    *xml_child_each(cxobj *xparent, cxobj *xprev,  enum cxobj_type type);
189 
190 int       xml_child_insert_pos(cxobj *x, cxobj *xc, int i);
191 int       xml_childvec_set(cxobj *x, int len);
192 cxobj   **xml_childvec_get(cxobj *x);
193 cxobj    *xml_new(char *name, cxobj *xn_parent, enum cxobj_type type);
194 cxobj    *xml_new_body(char *name, cxobj *parent, char *val);
195 yang_stmt *xml_spec(cxobj *x);
196 int       xml_spec_set(cxobj *x, yang_stmt *spec);
197 cg_var   *xml_cv(cxobj *x);
198 int       xml_cv_set(cxobj *x, cg_var *cv);
199 cxobj    *xml_find(cxobj *xn_parent, char *name);
200 int       xml_addsub(cxobj *xp, cxobj *xc);
201 cxobj    *xml_wrap_all(cxobj *xp, char *tag);
202 cxobj    *xml_wrap(cxobj *xc, char *tag);
203 int       xml_purge(cxobj *xc);
204 int       xml_child_rm(cxobj *xp, int i);
205 int       xml_rm(cxobj *xc);
206 int       xml_rm_children(cxobj *x, enum cxobj_type type);
207 int       xml_rootchild(cxobj  *xp, int i, cxobj **xcp);
208 int       xml_rootchild_node(cxobj  *xp, cxobj *xc);
209 int       xml_enumerate_children(cxobj *xp);
210 int       xml_enumerate_reset(cxobj *xp);
211 int       xml_enumerate_get(cxobj *x);
212 
213 char     *xml_body(cxobj *xn);
214 cxobj    *xml_body_get(cxobj *xn);
215 char     *xml_find_type_value(cxobj *xn_parent, const char *prefix,
216 			      const char *name, enum cxobj_type type);
217 cxobj    *xml_find_type(cxobj *xn_parent, const char *prefix, const char *name, enum cxobj_type type);
218 char     *xml_find_value(cxobj *xn_parent, const char *name);
219 char     *xml_find_body(cxobj *xn, const char *name);
220 cxobj    *xml_find_body_obj(cxobj *xt, const char *name, char *val);
221 
222 int       xml_free(cxobj *xn);
223 
224 int       xml_copy_one(cxobj *xn0, cxobj *xn1);
225 int       xml_copy(cxobj *x0, cxobj *x1);
226 cxobj    *xml_dup(cxobj *x0);
227 
228 int       cxvec_dup(cxobj **vec0, int len0, cxobj ***vec1, int *len1);
229 int       cxvec_append(cxobj *x, cxobj ***vec, int *len);
230 int       cxvec_prepend(cxobj *x, cxobj ***vec, int *len);
231 int       xml_apply(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
232 int       xml_apply0(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
233 int       xml_apply_ancestor(cxobj *xn, xml_applyfn_t fn, void *arg);
234 int       xml_isancestor(cxobj *x, cxobj *xp);
235 cxobj    *xml_root(cxobj *xn);
236 
237 int       xml_operation(char *opstr, enum operation_type *op);
238 char     *xml_operation2str(enum operation_type op);
239 int       xml_attr_insert2val(char *instr, enum insert_type *ins);
240 #if defined(__GNUC__) && __GNUC__ >= 3
241 int       clicon_log_xml(int level, cxobj *x, const char *format, ...)  __attribute__ ((format (printf, 3, 4)));
242 #else
243 int       clicon_log_xml(int level, cxobj *x, const char *format, ...);
244 #endif
245 #ifdef XML_EXPLICIT_INDEX
246 int       xml_search_index_p(cxobj *x);
247 
248 int       xml_search_vector_get(cxobj *x, char *name, clixon_xvec **xvec);
249 int       xml_search_child_insert(cxobj *xp, cxobj *x);
250 int       xml_search_child_rm(cxobj *xp, cxobj *x);
251 cxobj    *xml_child_index_each(cxobj *xparent, char *name, cxobj *xprev, enum cxobj_type type);
252 
253 
254 #endif
255 
256 #endif /* _CLIXON_XML_H */
257