@@ -296,13 +296,13 @@ schema_mount_get_smount(const struct lysc_ext_instance *ext, const struct lyd_no
296296 * @brief Create schema (context) based on retrieved extension data.
297297 *
298298 * @param[in] ext Compiled extension instance.
299- * @param[in] ext_data Extension data retrieved by the callback .
299+ * @param[in] ext_yl_data Extension data 'yang-library' subtree .
300300 * @param[in] config Whether the whole schema should keep its config or be set to false.
301301 * @param[out] ext_ctx Schema to use for parsing the data.
302302 * @return LY_ERR value.
303303 */
304304static LY_ERR
305- schema_mount_create_ctx (const struct lysc_ext_instance * ext , const struct lyd_node * ext_data , ly_bool config ,
305+ schema_mount_create_ctx (const struct lysc_ext_instance * ext , const struct lyd_node * ext_yl_data , ly_bool config ,
306306 struct ly_ctx * * ext_ctx )
307307{
308308 LY_ERR rc = LY_SUCCESS ;
@@ -325,7 +325,7 @@ schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_no
325325 }
326326
327327 /* create the context based on the data */
328- if ((rc = ly_ctx_new_yldata (sdirs , ext_data , ly_ctx_get_options (ext -> module -> ctx ), ext_ctx ))) {
328+ if ((rc = ly_ctx_new_yldata (sdirs , ext_yl_data , ly_ctx_get_options (ext -> module -> ctx ), ext_ctx ))) {
329329 lyplg_ext_compile_log (NULL , ext , LY_LLERR , rc , "Failed to create context for the schema-mount data (%s)." ,
330330 ly_last_logmsg ());
331331 goto cleanup ;
@@ -357,35 +357,102 @@ schema_mount_create_ctx(const struct lysc_ext_instance *ext, const struct lyd_no
357357 return rc ;
358358}
359359
360+ /**
361+ * @brief Get ietf-yang-library from ext data specific for this extension.
362+ *
363+ * @param[in] ext Compiled extension instance.
364+ * @param[in] ext_data Extension data retrieved by the callback with the yang-library data.
365+ * @param[in] parent Optional data parent to use.
366+ * @param[in] shared Whether the 'mount-point' is shared or inline.
367+ * @param[out] ext_yl_data Data tree 'yang-library' of @p ext.
368+ * @return LY_ERR value.
369+ */
370+ static LY_ERR
371+ schema_mount_get_yanglib (const struct lysc_ext_instance * ext , const struct lyd_node * ext_data ,
372+ const struct lyd_node * parent , ly_bool shared , const struct lyd_node * * ext_yl_data )
373+ {
374+ LY_ERR rc = LY_SUCCESS ;
375+ char * parent_path = NULL ;
376+ struct lyd_node * iter ;
377+ struct ly_set * set = NULL ;
378+ uint32_t i ;
379+
380+ * ext_yl_data = NULL ;
381+
382+ if (!shared ) {
383+ /* inline context is built from the parent context 'yang-library' data */
384+ lyd_find_path (ext_data , "/ietf-yang-library:yang-library" , 0 , (struct lyd_node * * )ext_yl_data );
385+ } else {
386+ if (parent ) {
387+ /* path of the data parent in data */
388+ parent_path = lyd_path (parent , LYD_PATH_STD , NULL , 0 );
389+ } else {
390+ /* path of the ext schema node parent */
391+ parent_path = lysc_path (ext -> parent , LYSC_PATH_DATA , NULL , 0 );
392+ }
393+
394+ /* get the parent(s) of 'yang-library' */
395+ if ((rc = lyd_find_xpath (ext_data , parent_path , & set ))) {
396+ goto cleanup ;
397+ }
398+
399+ /* find manually, may be from a different context */
400+ for (i = 0 ; i < set -> count ; ++ i ) {
401+ LY_LIST_FOR (lyd_child (set -> dnodes [i ]), iter ) {
402+ if (!strcmp (LYD_NAME (iter ), "yang-library" ) && !strcmp (lyd_node_module (iter )-> name , "ietf-yang-library" )) {
403+ /* first match should be fine */
404+ * ext_yl_data = iter ;
405+ break ;
406+ }
407+ }
408+ if (iter ) {
409+ break ;
410+ }
411+ }
412+ }
413+
414+ if (!* ext_yl_data ) {
415+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EVALID , "Could not find 'yang-library' data in \"%s\"." ,
416+ parent_path ? parent_path : "<top-level>" );
417+ rc = LY_EVALID ;
418+ goto cleanup ;
419+ }
420+
421+ cleanup :
422+ free (parent_path );
423+ ly_set_free (set , NULL );
424+ return rc ;
425+ }
426+
360427/**
361428 * @brief Get ietf-yang-library context-id from its data.
362429 *
363430 * @param[in] ext Compiled extension instance for logging.
364- * @param[in] ext_data Extension data retrieved by the callback with the yang-library data .
365- * @param[out] content_id Content ID in @p ext_data .
431+ * @param[in] ext_yl_data Extension data subtree ' yang-library' .
432+ * @param[out] content_id Content ID of @p ext_yl_data .
366433 * @return LY_ERR value.
367434 */
368435static LY_ERR
369- schema_mount_get_content_id (struct lysc_ext_instance * ext , const struct lyd_node * ext_data , const char * * content_id )
436+ schema_mount_get_content_id (struct lysc_ext_instance * ext , const struct lyd_node * ext_yl_data , const char * * content_id )
370437{
371438 struct lyd_node * node = NULL ;
439+ const struct lysc_node * snode ;
440+
441+ assert (ext_yl_data && !strcmp (LYD_NAME (ext_yl_data ), "yang-library" ));
372442
373443 * content_id = NULL ;
374444
375- /* get yang-library content-id or module-set-id */
376- if (ext_data ) {
377- lyd_find_path (ext_data , "/ietf-yang-library:yang-library/content-id" , 0 , & node );
378- if (!node ) {
379- lyd_find_path (ext_data , "/ietf-yang-library:modules-state/module-set-id" , 0 , & node );
380- }
381- if (node ) {
382- * content_id = lyd_get_value (node );
383- }
445+ /* find the content-id node */
446+ snode = lys_find_child (ext_yl_data -> schema , ext_yl_data -> schema -> module , "content-id" , 0 , 0 , 0 );
447+ assert (snode );
448+
449+ /* get yang-library content-id */
450+ if (!lyd_find_sibling_val (lyd_child (ext_yl_data ), snode , NULL , 0 , & node )) {
451+ * content_id = lyd_get_value (node );
384452 }
385453
386454 if (!* content_id ) {
387- lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EVALID ,
388- "Missing \"content-id\" or \"module-set-id\" in ietf-yang-library data." );
455+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EVALID , "Missing \"content-id\" in ietf-yang-library data." );
389456 return LY_EVALID ;
390457 }
391458 return LY_SUCCESS ;
@@ -406,6 +473,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
406473{
407474 struct lyplg_ext_sm * sm_data = ext -> compiled ;
408475 LY_ERR rc = LY_SUCCESS , r ;
476+ const struct lyd_node * ext_yl_data ;
409477 struct ly_ctx * new_ctx = NULL ;
410478 uint32_t i ;
411479 const char * content_id ;
@@ -417,8 +485,13 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
417485 * ext_ctx = NULL ;
418486 }
419487
488+ /* get yang-library data */
489+ if ((r = schema_mount_get_yanglib (ext , ext_data , NULL , 1 , & ext_yl_data ))) {
490+ return r ;
491+ }
492+
420493 /* get yang-library content-id or module-set-id */
421- if ((r = schema_mount_get_content_id (ext , ext_data , & content_id ))) {
494+ if ((r = schema_mount_get_content_id (ext , ext_yl_data , & content_id ))) {
422495 return r ;
423496 }
424497
@@ -440,7 +513,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
440513 if (i < sm_data -> shared -> schema_count ) {
441514 /* schema exists already */
442515 if (strcmp (content_id , sm_data -> shared -> schemas [i ].content_id )) {
443- lyplg_ext_compile_log_path ( "/ietf-yang-library:yang-library/content-id" , ext , LY_LLERR , LY_EVALID ,
516+ lyplg_ext_compile_log ( NULL , ext , LY_LLERR , LY_EVALID ,
444517 "Shared-schema yang-library content-id \"%s\" differs from \"%s\" used previously." ,
445518 content_id , sm_data -> shared -> schemas [i ].content_id );
446519 rc = LY_EVALID ;
@@ -458,7 +531,7 @@ schema_mount_get_ctx_shared(struct lysc_ext_instance *ext, const struct lyd_node
458531 }
459532
460533 /* no schema found, create it */
461- if ((r = schema_mount_create_ctx (ext , ext_data , config , & new_ctx ))) {
534+ if ((r = schema_mount_create_ctx (ext , ext_yl_data , config , & new_ctx ))) {
462535 rc = r ;
463536 goto cleanup ;
464537 }
@@ -711,6 +784,7 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node
711784{
712785 struct lyplg_ext_sm * sm_data = ext -> compiled ;
713786 struct ly_ctx * new_ctx = NULL ;
787+ const struct lyd_node * ext_yl_data ;
714788 uint32_t i ;
715789 void * mem ;
716790 LY_ERR rc = LY_SUCCESS , r ;
@@ -746,8 +820,14 @@ schema_mount_get_ctx_inline(struct lysc_ext_instance *ext, const struct lyd_node
746820 }
747821 }
748822
823+ /* find the 'yang-library' data */
824+ if ((r = schema_mount_get_yanglib (ext , ext_data , NULL , 0 , & ext_yl_data ))) {
825+ rc = r ;
826+ goto cleanup ;
827+ }
828+
749829 /* new schema required, create context */
750- if ((r = schema_mount_create_ctx (ext , ext_data , config , & new_ctx ))) {
830+ if ((r = schema_mount_create_ctx (ext , ext_yl_data , config , & new_ctx ))) {
751831 rc = r ;
752832 goto cleanup ;
753833 }
@@ -786,7 +866,7 @@ LY_ERR
786866lyplg_ext_schema_mount_get_ctx (struct lysc_ext_instance * ext , const struct lyd_node * parent , const struct ly_ctx * * ext_ctx )
787867{
788868 LY_ERR ret = LY_SUCCESS , r ;
789- struct lyd_node * iter , * ext_data = NULL ;
869+ struct lyd_node * ext_data = NULL , * sm_root = NULL ;
790870 ly_bool ext_data_free = 0 , config , shared ;
791871
792872 * ext_ctx = NULL ;
@@ -797,13 +877,27 @@ lyplg_ext_schema_mount_get_ctx(struct lysc_ext_instance *ext, const struct lyd_n
797877 goto cleanup ;
798878 }
799879
800- LY_LIST_FOR (ext_data , iter ) {
801- if (iter -> flags & LYD_NEW ) {
802- /* must be validated for the parent-reference prefix data to be stored */
803- lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EINVAL , "Provided ext data have not been validated." );
804- ret = LY_EINVAL ;
805- goto cleanup ;
806- }
880+ if (!ext_data ) {
881+ * ext_ctx = ext -> module -> ctx ;
882+ goto cleanup ;
883+ }
884+
885+ if ((r = lyd_find_path (ext_data , "/ietf-yang-schema-mount:schema-mounts" , 0 , & sm_root ))) {
886+ ret = r ;
887+ goto cleanup ;
888+ }
889+ if (!sm_root ) {
890+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_ENOT ,
891+ "Missing \"ietf-yang-schema-mount:schema-mounts\" in provided extension data." );
892+ ret = LY_ENOT ;
893+ goto cleanup ;
894+ }
895+
896+ /* must be validated for the parent-reference prefix data to be stored, only sm data root check is sufficient */
897+ if (sm_root -> flags & LYD_NEW ) {
898+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EINVAL , "Provided ext data have not been validated." );
899+ ret = LY_EINVAL ;
900+ goto cleanup ;
807901 }
808902
809903 /* learn about this mount point */
@@ -857,6 +951,12 @@ schema_mount_snode(struct lysc_ext_instance *ext, const struct lyd_node *parent,
857951 return LY_ENOT ;
858952 }
859953
954+ if ((ext -> module -> ctx == ext_ctx ) && strcmp (mod -> name , "ietf-yang-library" )) {
955+ /* without explicit 'ietf-yang-schema-mount' and 'ietf-yang-library' data we can parse only mounted
956+ * 'ietf-yang-library' data */
957+ return LY_ENOT ;
958+ }
959+
860960 /* get the top-level schema node */
861961 * snode = lys_find_child (NULL , mod , name , name_len , 0 , 0 );
862962 return * snode ? LY_SUCCESS : LY_ENOT ;
@@ -1060,7 +1160,7 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c
10601160 LY_ERR ret = LY_SUCCESS ;
10611161 uint32_t i ;
10621162 struct lyd_node * iter , * ext_data = NULL , * ref_first = NULL , * orig_parent = lyd_parent (sibling ), * op_tree ;
1063- struct lyd_node * ext_diff = NULL , * diff_parent = NULL ;
1163+ struct lyd_node * ext_diff = NULL , * diff_parent = NULL , * sm_root = NULL ;
10641164 ly_bool ext_data_free = 0 ;
10651165 struct ly_set * ref_set = NULL ;
10661166
@@ -1073,14 +1173,28 @@ schema_mount_validate(struct lysc_ext_instance *ext, struct lyd_node *sibling, c
10731173 if ((ret = lyplg_ext_get_data (ext -> module -> ctx , ext , lyd_parent (sibling ), (void * * )& ext_data , & ext_data_free ))) {
10741174 goto cleanup ;
10751175 }
1176+ if (!ext_data ) {
1177+ /* ext data must have been provided */
1178+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EINVAL , "No ext data provided for schema mount validation." );
1179+ ret = LY_EINVAL ;
1180+ goto cleanup ;
1181+ }
10761182
1077- LY_LIST_FOR (ext_data , iter ) {
1078- if (iter -> flags & LYD_NEW ) {
1079- /* must be validated for the parent-reference prefix data to be stored */
1080- lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EINVAL , "Provided ext data have not been validated." );
1081- ret = LY_EINVAL ;
1082- goto cleanup ;
1083- }
1183+ if ((ret = lyd_find_path (ext_data , "/ietf-yang-schema-mount:schema-mounts" , 0 , & sm_root ))) {
1184+ goto cleanup ;
1185+ }
1186+ if (!sm_root ) {
1187+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_ENOT ,
1188+ "Missing \"ietf-yang-schema-mount:schema-mounts\" in provided extension data." );
1189+ ret = LY_ENOT ;
1190+ goto cleanup ;
1191+ }
1192+
1193+ /* must be validated for the parent-reference prefix data to be stored, only sm data root check is sufficient */
1194+ if (sm_root -> flags & LYD_NEW ) {
1195+ lyplg_ext_compile_log (NULL , ext , LY_LLERR , LY_EINVAL , "Provided ext data have not been validated." );
1196+ ret = LY_EINVAL ;
1197+ goto cleanup ;
10841198 }
10851199
10861200 /* duplicate the referenced parent nodes into ext context */
@@ -1214,6 +1328,7 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const
12141328 LY_ERR rc = LY_SUCCESS ;
12151329 uint32_t i ;
12161330 ly_ext_data_clb ext_data_clb ;
1331+ const struct lyd_node * ext_yl_data ;
12171332
12181333 LY_CHECK_ARG_RET (NULL , ext , ctx , LY_EINVAL );
12191334
@@ -1275,8 +1390,15 @@ lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, const
12751390 goto cleanup ;
12761391 }
12771392
1393+ /* find 'yang-library' data */
1394+ if ((rc = schema_mount_get_yanglib (ext , ext_data , parent , shared , & ext_yl_data ))) {
1395+ goto cleanup ;
1396+ }
1397+
12781398 /* create the context */
1279- rc = schema_mount_create_ctx (ext , ext_data , config , ctx );
1399+ if ((rc = schema_mount_create_ctx (ext , ext_yl_data , config , ctx ))) {
1400+ goto cleanup ;
1401+ }
12801402
12811403cleanup :
12821404 if (ext_data_free ) {
0 commit comments