kly.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. char *space = NULL;
  114. char *escaped = NULL;
  115. char *result = NULL;
  116. if (!node)
  117. return NULL;
  118. schema = node->schema;
  119. if (!(schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  120. return NULL;
  121. if (schema->nodetype & LYS_LEAF)
  122. type = ((const struct lysc_node_leaf *)schema)->type;
  123. else
  124. type = ((const struct lysc_node_leaflist *)schema)->type;
  125. if (type->basetype != LY_TYPE_IDENT) {
  126. origin_value = lyd_get_value(node);
  127. } else {
  128. // Identity
  129. const struct lyd_value *value = NULL;
  130. value = &((const struct lyd_node_term *)node)->value;
  131. origin_value = value->ident->name;
  132. }
  133. escaped = faux_str_c_esc(origin_value);
  134. // String with space must have quotes
  135. space = strchr(origin_value, ' ');
  136. if (space) {
  137. result = faux_str_sprintf("\"%s\"", escaped);
  138. faux_str_free(escaped);
  139. } else {
  140. result = escaped;
  141. }
  142. return result;
  143. }
  144. // Don't use standard lys_find_child() because it checks given module to be
  145. // equal to found node's module. So augmented nodes will not be found.
  146. const struct lysc_node *klysc_find_child(const struct lysc_node *node,
  147. const char *name)
  148. {
  149. const struct lysc_node *iter = NULL;
  150. if (!node)
  151. return NULL;
  152. LY_LIST_FOR(node, iter) {
  153. if (!(iter->nodetype & SRP_NODETYPE_CONF))
  154. continue;
  155. if (!(iter->flags & LYS_CONFIG_W))
  156. continue;
  157. // Special case. LYS_CHOICE and LYS_CASE must search for
  158. // specified name inside themselfs.
  159. if (iter->nodetype & (LYS_CHOICE | LYS_CASE)) {
  160. const struct lysc_node *node_in = NULL;
  161. node_in = klysc_find_child(lysc_node_child(iter), name);
  162. if (node_in)
  163. return node_in;
  164. continue;
  165. }
  166. if (!faux_str_cmp(iter->name, name))
  167. return iter;
  168. }
  169. return NULL;
  170. }
  171. static struct lysc_ident *klysc_find_ident(struct lysc_ident *ident, const char *name)
  172. {
  173. LY_ARRAY_COUNT_TYPE u = 0;
  174. if (!ident)
  175. return NULL;
  176. if (!ident->derived) {
  177. if (!faux_str_cmp(name, ident->name))
  178. return ident;
  179. return NULL;
  180. }
  181. LY_ARRAY_FOR(ident->derived, u) {
  182. struct lysc_ident *identity = klysc_find_ident(ident->derived[u], name);
  183. if (identity)
  184. return identity;
  185. }
  186. return NULL;
  187. }
  188. const char *klysc_identityref_prefix(struct lysc_type_identityref *type,
  189. const char *name)
  190. {
  191. LY_ARRAY_COUNT_TYPE u = 0;
  192. assert(type);
  193. LY_ARRAY_FOR(type->bases, u) {
  194. struct lysc_ident *identity = klysc_find_ident(type->bases[u], name);
  195. if (identity)
  196. return identity->module->name;
  197. }
  198. return NULL;
  199. }
  200. // Get module name by internal prefix. Sysrepo requests use module names but not
  201. // prefixes.
  202. static const char *module_by_prefix(const struct lysp_module *parsed, const char *prefix)
  203. {
  204. LY_ARRAY_COUNT_TYPE u = 0;
  205. if (!parsed)
  206. return NULL;
  207. if (!prefix)
  208. return NULL;
  209. // Try prefix of module itself
  210. if (faux_str_cmp(prefix, parsed->mod->prefix) == 0)
  211. return parsed->mod->name;
  212. // Try imported modules
  213. LY_ARRAY_FOR(parsed->imports, u) {
  214. const struct lysp_import *import = &parsed->imports[u];
  215. if (faux_str_cmp(prefix, import->prefix) == 0)
  216. return import->name;
  217. }
  218. return NULL;
  219. }
  220. static char *remap_xpath_prefixes(const char *orig_xpath, const struct lysp_module *parsed)
  221. {
  222. char *remaped = NULL;
  223. const char *pos = orig_xpath;
  224. const char *start = orig_xpath;
  225. char *cached_prefix = NULL;
  226. char *cached_module = NULL;
  227. if (!orig_xpath)
  228. return NULL;
  229. while (*pos != '\0') {
  230. if (*pos == '/') {
  231. faux_str_catn(&remaped, start, pos - start + 1);
  232. start = pos + 1;
  233. } else if (*pos == ':') {
  234. if (pos != start) {
  235. char *prefix = faux_str_dupn(start, pos - start);
  236. if (cached_prefix && (faux_str_cmp(prefix, cached_prefix) == 0)) {
  237. faux_str_cat(&remaped, cached_module);
  238. faux_str_free(prefix);
  239. } else {
  240. const char *module = module_by_prefix(parsed, prefix);
  241. if (module) {
  242. faux_str_cat(&remaped, module);
  243. faux_str_free(cached_prefix);
  244. faux_str_free(cached_module);
  245. cached_prefix = prefix;
  246. cached_module = faux_str_dup(module);
  247. } else {
  248. faux_str_cat(&remaped, prefix);
  249. faux_str_free(prefix);
  250. }
  251. }
  252. }
  253. faux_str_cat(&remaped, ":");
  254. start = pos + 1;
  255. }
  256. pos++;
  257. }
  258. if (start != pos)
  259. faux_str_catn(&remaped, start, pos - start);
  260. faux_str_free(cached_prefix);
  261. faux_str_free(cached_module);
  262. return remaped;
  263. }
  264. static const char *cut_front_ups(const char *orig_xpath, size_t *up_num)
  265. {
  266. const char *xpath = orig_xpath;
  267. const char *needle = "../";
  268. size_t needle_len = strlen(needle);
  269. size_t num = 0;
  270. if (!xpath)
  271. return NULL;
  272. while (faux_str_cmpn(xpath, needle, needle_len) == 0) {
  273. num++;
  274. xpath += needle_len;
  275. }
  276. if (up_num)
  277. *up_num = num;
  278. return xpath;
  279. }
  280. static char *cut_trailing_components(const char *orig_xpath, size_t up_num)
  281. {
  282. const char *xpath = NULL;
  283. char *res = NULL;
  284. size_t num = 0;
  285. if (!orig_xpath)
  286. return NULL;
  287. xpath = orig_xpath + strlen(orig_xpath);
  288. while (xpath >= orig_xpath) {
  289. if (*xpath == '/')
  290. num++;
  291. if (num == up_num) {
  292. res = faux_str_dupn(orig_xpath, xpath - orig_xpath + 1);
  293. break;
  294. }
  295. xpath--;
  296. }
  297. return res;
  298. }
  299. char *klysc_leafref_xpath(const struct lysc_node *node,
  300. const struct lysc_type *type, const char *node_path)
  301. {
  302. char *compl_xpath = NULL;
  303. const struct lysc_type_leafref *leafref = NULL;
  304. const char *orig_xpath = NULL;
  305. char *remaped_xpath = NULL;
  306. const char *tmp = NULL;
  307. size_t up_num = 0;
  308. if (!type)
  309. return NULL;
  310. if (!node)
  311. return NULL;
  312. if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  313. return NULL;
  314. if (type->basetype != LY_TYPE_LEAFREF)
  315. return NULL;
  316. leafref = (const struct lysc_type_leafref *)type;
  317. orig_xpath = lyxp_get_expr(leafref->path);
  318. if (!orig_xpath)
  319. return NULL;
  320. remaped_xpath = remap_xpath_prefixes(orig_xpath, node->module->parsed);
  321. if (remaped_xpath[0] == '/') // Absolute path
  322. return remaped_xpath;
  323. // Relative path
  324. if (!node_path) {
  325. faux_str_free(remaped_xpath);
  326. return NULL;
  327. }
  328. tmp = cut_front_ups(remaped_xpath, &up_num);
  329. compl_xpath = cut_trailing_components(node_path, up_num);
  330. if (!compl_xpath) {
  331. faux_str_free(remaped_xpath);
  332. return NULL;
  333. }
  334. faux_str_cat(&compl_xpath, tmp);
  335. faux_str_free(remaped_xpath);
  336. return compl_xpath;
  337. }
  338. size_t klyd_visible_child_num(const struct lyd_node *node)
  339. {
  340. const struct lyd_node *nodes_list = NULL;
  341. const struct lyd_node *iter = NULL;
  342. size_t num = 0;
  343. if (!node)
  344. return 0;
  345. nodes_list = lyd_child(node);
  346. if(!nodes_list)
  347. return 0;
  348. LY_LIST_FOR(nodes_list, iter) {
  349. if (iter->flags & LYD_DEFAULT)
  350. continue;
  351. if (!(iter->schema->nodetype & SRP_NODETYPE_CONF))
  352. continue;
  353. if (!(iter->schema->flags & LYS_CONFIG_W)) // config is true
  354. continue;
  355. if (iter->schema->flags & LYS_KEY)
  356. continue;
  357. num++;
  358. }
  359. return num;
  360. }
  361. bool_t kly_str2ds(const char *str, size_t len, sr_datastore_t *ds)
  362. {
  363. if (!str)
  364. return BOOL_FALSE;
  365. if (len == 0)
  366. return BOOL_FALSE;
  367. if (!ds)
  368. return BOOL_FALSE;
  369. if (faux_str_cmpn(str, "candidate", len) == 0)
  370. *ds = SR_DS_CANDIDATE;
  371. else if (faux_str_cmpn(str, "running", len) == 0)
  372. *ds = SR_DS_RUNNING;
  373. else if (faux_str_cmpn(str, "operational", len) == 0)
  374. *ds = SR_DS_OPERATIONAL;
  375. else if (faux_str_cmpn(str, "startup", len) == 0)
  376. *ds = SR_DS_STARTUP;
  377. #ifdef SR_DS_FACTORY_DEFAULT
  378. else if (faux_str_cmpn(str, "factory-default", len) == 0)
  379. *ds = SR_DS_FACTORY_DEFAULT;
  380. #endif
  381. else // No DS prefix found
  382. return BOOL_FALSE;
  383. return BOOL_TRUE;
  384. }
  385. bool_t kly_parse_ext_xpath(const char *xpath, const char **raw_xpath,
  386. sr_datastore_t *ds)
  387. {
  388. char *space = NULL;
  389. if (!xpath)
  390. return BOOL_FALSE;
  391. if (!raw_xpath)
  392. return BOOL_FALSE;
  393. if (!ds)
  394. return BOOL_FALSE;
  395. *ds = SRP_REPO_EDIT; // Default
  396. *raw_xpath = xpath;
  397. space = strchr(xpath, ' ');
  398. if (space) {
  399. size_t len = space - xpath;
  400. if (kly_str2ds(xpath, len, ds))
  401. *raw_xpath = space + 1;
  402. }
  403. return BOOL_TRUE;
  404. }