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