kly.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <syslog.h>
  7. #include <faux/faux.h>
  8. #include <faux/str.h>
  9. #include <faux/list.h>
  10. #include <faux/argv.h>
  11. #include <sysrepo.h>
  12. #include <sysrepo/xpath.h>
  13. #include <sysrepo/values.h>
  14. #include <libyang/tree_edit.h>
  15. #include "klish_plugin_sysrepo.h"
  16. int klysc_key_compare(const void *first, const void *second)
  17. {
  18. const klysc_key_t *f = (const klysc_key_t *)first;
  19. const klysc_key_t *s = (const klysc_key_t *)second;
  20. return strcmp(f->node->name, s->node->name);
  21. }
  22. int klysc_key_kcompare(const void *key, const void *list_item)
  23. {
  24. const char *f = (const char *)key;
  25. const klysc_key_t *s = (const klysc_key_t *)list_item;
  26. return strcmp(f, s->node->name);
  27. }
  28. // Get extension by name from schema node
  29. static bool_t klysc_ext(const struct lysc_ext_instance *exts,
  30. const char *module, const char *name, const char **argument)
  31. {
  32. LY_ARRAY_COUNT_TYPE u = 0;
  33. if (!exts)
  34. return BOOL_FALSE;
  35. LY_ARRAY_FOR(exts, u) {
  36. const struct lysc_ext_instance *ext = &exts[u];
  37. //syslog(LOG_ERR, "mod: %s, ext: %s", ext->def->module->name, ext->def->name);
  38. if (faux_str_cmp(ext->def->module->name, module) != 0)
  39. continue;
  40. if (faux_str_cmp(ext->def->name, name) != 0)
  41. continue;
  42. if (argument)
  43. *argument = ext->argument;
  44. return BOOL_TRUE;
  45. }
  46. return BOOL_FALSE;
  47. }
  48. // Get extension by name from node
  49. bool_t klysc_node_ext(const struct lysc_node *node,
  50. const char *module, const char *name, const char **argument)
  51. {
  52. if (!node)
  53. return BOOL_FALSE;
  54. if (klysc_ext(node->exts, module, name, argument))
  55. return BOOL_TRUE;
  56. return BOOL_FALSE;
  57. }
  58. // Get extension by name from type
  59. bool_t klysc_type_ext(const struct lysc_type *type,
  60. const char *module, const char *name, const char **argument)
  61. {
  62. if (!type)
  63. return BOOL_FALSE;
  64. if (klysc_ext(type->exts, module, name, argument))
  65. return BOOL_TRUE;
  66. return BOOL_FALSE;
  67. }
  68. // Get extension by name from node or type
  69. bool_t klysc_node_or_type_ext(const struct lysc_node *node,
  70. const char *module, const char *name, const char **argument)
  71. {
  72. struct lysc_type *type = NULL;
  73. if (!node)
  74. return BOOL_FALSE;
  75. if (klysc_node_ext(node, module, name, argument))
  76. return BOOL_TRUE;
  77. switch (node->nodetype) {
  78. case LYS_LEAF:
  79. type = ((struct lysc_node_leaf *)node)->type;
  80. break;
  81. case LYS_LEAFLIST:
  82. type = ((struct lysc_node_leaflist *)node)->type;
  83. break;
  84. default:
  85. return BOOL_FALSE;
  86. }
  87. if (klysc_type_ext(type, module, name, argument))
  88. return BOOL_TRUE;
  89. return BOOL_FALSE;
  90. }
  91. bool_t klysc_node_ext_is_password(const struct lysc_node *node)
  92. {
  93. return klysc_node_ext(node, "klish", "password", NULL);
  94. }
  95. const char *klysc_node_ext_completion(const struct lysc_node *node)
  96. {
  97. const char *xpath = NULL;
  98. klysc_node_or_type_ext(node, "klish", "completion", &xpath);
  99. return xpath;
  100. }
  101. const char *klysc_node_ext_default(const struct lysc_node *node)
  102. {
  103. const char *dflt = NULL;
  104. klysc_node_ext(node, "klish", "default", &dflt);
  105. return dflt;
  106. }
  107. // Get value from data lyd node
  108. char *klyd_node_value(const struct lyd_node *node)
  109. {
  110. const struct lysc_node *schema = NULL;
  111. const struct lysc_type *type = NULL;
  112. const char *origin_value = NULL;
  113. if (!node)
  114. return NULL;
  115. schema = node->schema;
  116. if (!(schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  117. return NULL;
  118. if (schema->nodetype & LYS_LEAF)
  119. type = ((const struct lysc_node_leaf *)schema)->type;
  120. else
  121. type = ((const struct lysc_node_leaflist *)schema)->type;
  122. if (type->basetype != LY_TYPE_IDENT) {
  123. origin_value = lyd_get_value(node);
  124. } else {
  125. // Identity
  126. const struct lyd_value *value = NULL;
  127. value = &((const struct lyd_node_term *)node)->value;
  128. origin_value = value->ident->name;
  129. }
  130. return faux_str_c_esc_quote(origin_value);
  131. }
  132. // Don't use standard lys_find_child() because it checks given module to be
  133. // equal to found node's module. So augmented nodes will not be found.
  134. const struct lysc_node *klysc_find_child(const struct lysc_node *node,
  135. const char *name)
  136. {
  137. const struct lysc_node *iter = NULL;
  138. if (!node)
  139. return NULL;
  140. LY_LIST_FOR(node, iter) {
  141. if (!(iter->nodetype & SRP_NODETYPE_CONF))
  142. continue;
  143. if (!(iter->flags & LYS_CONFIG_W))
  144. continue;
  145. // Special case. LYS_CHOICE and LYS_CASE must search for
  146. // specified name inside themselfs.
  147. if (iter->nodetype & (LYS_CHOICE | LYS_CASE)) {
  148. const struct lysc_node *node_in = NULL;
  149. node_in = klysc_find_child(lysc_node_child(iter), name);
  150. if (node_in)
  151. return node_in;
  152. continue;
  153. }
  154. if (!faux_str_cmp(iter->name, name))
  155. return iter;
  156. }
  157. return NULL;
  158. }
  159. static struct lysc_ident *klysc_find_ident(struct lysc_ident *ident, const char *name)
  160. {
  161. LY_ARRAY_COUNT_TYPE u = 0;
  162. if (!ident)
  163. return NULL;
  164. if (!ident->derived) {
  165. if (!faux_str_cmp(name, ident->name))
  166. return ident;
  167. return NULL;
  168. }
  169. LY_ARRAY_FOR(ident->derived, u) {
  170. struct lysc_ident *identity = klysc_find_ident(ident->derived[u], name);
  171. if (identity)
  172. return identity;
  173. }
  174. return NULL;
  175. }
  176. const char *klysc_identityref_prefix(struct lysc_type_identityref *type,
  177. const char *name)
  178. {
  179. LY_ARRAY_COUNT_TYPE u = 0;
  180. assert(type);
  181. LY_ARRAY_FOR(type->bases, u) {
  182. struct lysc_ident *identity = klysc_find_ident(type->bases[u], name);
  183. if (identity)
  184. return identity->module->name;
  185. }
  186. return NULL;
  187. }
  188. // Get module name by internal prefix. Sysrepo requests use module names but not
  189. // prefixes.
  190. static const char *module_by_prefix(const struct lysp_module *parsed, const char *prefix)
  191. {
  192. LY_ARRAY_COUNT_TYPE u = 0;
  193. if (!parsed)
  194. return NULL;
  195. if (!prefix)
  196. return NULL;
  197. // Try prefix of module itself
  198. if (faux_str_cmp(prefix, parsed->mod->prefix) == 0)
  199. return parsed->mod->name;
  200. // Try imported modules
  201. LY_ARRAY_FOR(parsed->imports, u) {
  202. const struct lysp_import *import = &parsed->imports[u];
  203. if (faux_str_cmp(prefix, import->prefix) == 0)
  204. return import->name;
  205. }
  206. return NULL;
  207. }
  208. static char *remap_xpath_prefixes(const char *orig_xpath, const struct lysp_module *parsed)
  209. {
  210. char *remaped = NULL;
  211. const char *pos = orig_xpath;
  212. const char *start = orig_xpath;
  213. char *cached_prefix = NULL;
  214. char *cached_module = NULL;
  215. if (!orig_xpath)
  216. return NULL;
  217. while (*pos != '\0') {
  218. if (*pos == '/') {
  219. faux_str_catn(&remaped, start, pos - start + 1);
  220. start = pos + 1;
  221. } else if (*pos == ':') {
  222. if (pos != start) {
  223. char *prefix = faux_str_dupn(start, pos - start);
  224. if (cached_prefix && (faux_str_cmp(prefix, cached_prefix) == 0)) {
  225. faux_str_cat(&remaped, cached_module);
  226. faux_str_free(prefix);
  227. } else {
  228. const char *module = module_by_prefix(parsed, prefix);
  229. if (module) {
  230. faux_str_cat(&remaped, module);
  231. faux_str_free(cached_prefix);
  232. faux_str_free(cached_module);
  233. cached_prefix = prefix;
  234. cached_module = faux_str_dup(module);
  235. } else {
  236. faux_str_cat(&remaped, prefix);
  237. faux_str_free(prefix);
  238. }
  239. }
  240. }
  241. faux_str_cat(&remaped, ":");
  242. start = pos + 1;
  243. }
  244. pos++;
  245. }
  246. if (start != pos)
  247. faux_str_catn(&remaped, start, pos - start);
  248. faux_str_free(cached_prefix);
  249. faux_str_free(cached_module);
  250. return remaped;
  251. }
  252. static const char *cut_front_ups(const char *orig_xpath, size_t *up_num)
  253. {
  254. const char *xpath = orig_xpath;
  255. const char *needle = "../";
  256. size_t needle_len = strlen(needle);
  257. size_t num = 0;
  258. if (!xpath)
  259. return NULL;
  260. while (faux_str_cmpn(xpath, needle, needle_len) == 0) {
  261. num++;
  262. xpath += needle_len;
  263. }
  264. if (up_num)
  265. *up_num = num;
  266. return xpath;
  267. }
  268. static char *cut_trailing_components(const char *orig_xpath, size_t up_num)
  269. {
  270. const char *xpath = NULL;
  271. char *res = NULL;
  272. size_t num = 0;
  273. if (!orig_xpath)
  274. return NULL;
  275. xpath = orig_xpath + strlen(orig_xpath);
  276. while (xpath >= orig_xpath) {
  277. if (*xpath == '/')
  278. num++;
  279. if (num == up_num) {
  280. res = faux_str_dupn(orig_xpath, xpath - orig_xpath + 1);
  281. break;
  282. }
  283. xpath--;
  284. }
  285. return res;
  286. }
  287. char *klysc_leafref_xpath(const struct lysc_node *node,
  288. const struct lysc_type *type, const char *node_path)
  289. {
  290. char *compl_xpath = NULL;
  291. const struct lysc_type_leafref *leafref = NULL;
  292. const char *orig_xpath = NULL;
  293. char *remaped_xpath = NULL;
  294. const char *tmp = NULL;
  295. size_t up_num = 0;
  296. if (!type)
  297. return NULL;
  298. if (!node)
  299. return NULL;
  300. if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  301. return NULL;
  302. if (type->basetype != LY_TYPE_LEAFREF)
  303. return NULL;
  304. leafref = (const struct lysc_type_leafref *)type;
  305. orig_xpath = lyxp_get_expr(leafref->path);
  306. if (!orig_xpath)
  307. return NULL;
  308. remaped_xpath = remap_xpath_prefixes(orig_xpath, node->module->parsed);
  309. if (remaped_xpath[0] == '/') // Absolute path
  310. return remaped_xpath;
  311. // Relative path
  312. if (!node_path) {
  313. faux_str_free(remaped_xpath);
  314. return NULL;
  315. }
  316. tmp = cut_front_ups(remaped_xpath, &up_num);
  317. compl_xpath = cut_trailing_components(node_path, up_num);
  318. if (!compl_xpath) {
  319. faux_str_free(remaped_xpath);
  320. return NULL;
  321. }
  322. faux_str_cat(&compl_xpath, tmp);
  323. faux_str_free(remaped_xpath);
  324. return compl_xpath;
  325. }
  326. size_t klyd_visible_child_num(const struct lyd_node *node)
  327. {
  328. const struct lyd_node *nodes_list = NULL;
  329. const struct lyd_node *iter = NULL;
  330. size_t num = 0;
  331. if (!node)
  332. return 0;
  333. nodes_list = lyd_child(node);
  334. if(!nodes_list)
  335. return 0;
  336. LY_LIST_FOR(nodes_list, iter) {
  337. if (iter->flags & LYD_DEFAULT)
  338. continue;
  339. if (!(iter->schema->nodetype & SRP_NODETYPE_CONF))
  340. continue;
  341. if (!(iter->schema->flags & LYS_CONFIG_W)) // config is true
  342. continue;
  343. if (iter->schema->flags & LYS_KEY)
  344. continue;
  345. num++;
  346. }
  347. return num;
  348. }
  349. bool_t kly_str2ds(const char *str, size_t len, sr_datastore_t *ds)
  350. {
  351. if (!str)
  352. return BOOL_FALSE;
  353. if (len == 0)
  354. return BOOL_FALSE;
  355. if (!ds)
  356. return BOOL_FALSE;
  357. if (faux_str_cmpn(str, "candidate", len) == 0)
  358. *ds = SR_DS_CANDIDATE;
  359. else if (faux_str_cmpn(str, "running", len) == 0)
  360. *ds = SR_DS_RUNNING;
  361. else if (faux_str_cmpn(str, "operational", len) == 0)
  362. *ds = SR_DS_OPERATIONAL;
  363. else if (faux_str_cmpn(str, "startup", len) == 0)
  364. *ds = SR_DS_STARTUP;
  365. #ifdef SR_DS_FACTORY_DEFAULT
  366. else if (faux_str_cmpn(str, "factory-default", len) == 0)
  367. *ds = SR_DS_FACTORY_DEFAULT;
  368. #endif
  369. else // No DS prefix found
  370. return BOOL_FALSE;
  371. return BOOL_TRUE;
  372. }
  373. bool_t kly_parse_ext_xpath(const char *xpath, const char **raw_xpath,
  374. sr_datastore_t *ds)
  375. {
  376. char *space = NULL;
  377. if (!xpath)
  378. return BOOL_FALSE;
  379. if (!raw_xpath)
  380. return BOOL_FALSE;
  381. if (!ds)
  382. return BOOL_FALSE;
  383. *ds = SRP_REPO_EDIT; // Default
  384. *raw_xpath = xpath;
  385. space = strchr(xpath, ' ');
  386. if (space) {
  387. size_t len = space - xpath;
  388. if (kly_str2ds(xpath, len, ds))
  389. *raw_xpath = space + 1;
  390. }
  391. return BOOL_TRUE;
  392. }