@@ -485,6 +485,46 @@ free_with_user_data(void *data, void *user_data)
485485 *
486486 * @param[in] mod_name Schema name.
487487 * @param[in] mod_rev Schema revision.
488+ * @param[in] user_data get-schema callback data.
489+ * @param[out] format Schema format.
490+ * @param[out] module_data Schema content.
491+ * @param[out] free_module_data Callback for freeing @p module_data.
492+ * @return LY_ERR value.
493+ */
494+ static LY_ERR
495+ retrieve_schema_data (const char * mod_name , const char * mod_rev , void * user_data , LYS_INFORMAT * format ,
496+ const char * * module_data , void (* * free_module_data )(void * model_data , void * user_data ))
497+ {
498+ struct clb_data_s * clb_data = (struct clb_data_s * )user_data ;
499+ char * model_data = NULL ;
500+
501+ VRB (clb_data -> session , "Retrieving data for schema \"%s\", revision \"%s\"." , mod_name , mod_rev ? mod_rev : "<latest>" );
502+
503+ /* 1. try to get data locally */
504+ model_data = retrieve_schema_data_localfile (mod_name , mod_rev , clb_data , format );
505+
506+ /* 2. try to use <get-schema> */
507+ if (!model_data && clb_data -> has_get_schema ) {
508+ model_data = retrieve_schema_data_getschema (mod_name , mod_rev , clb_data , format );
509+ }
510+
511+ /* 3. try to use user callback */
512+ if (!model_data && clb_data -> user_clb ) {
513+ VRB (clb_data -> session , "Reading schema via user callback." );
514+ clb_data -> user_clb (mod_name , mod_rev , NULL , NULL , clb_data -> user_data , format , (const char * * )& model_data ,
515+ free_module_data );
516+ }
517+
518+ * free_module_data = free_with_user_data ;
519+ * module_data = model_data ;
520+ return * module_data ? LY_SUCCESS : LY_ENOTFOUND ;
521+ }
522+
523+ /**
524+ * @brief Retrieve YANG import schema content.
525+ *
526+ * @param[in] mod_name Schema name.
527+ * @param[in] mod_rev Schema revision.
488528 * @param[in] submod_name Optional submodule name.
489529 * @param[in] sub_rev Submodule revision.
490530 * @param[in] user_data get-schema callback data.
@@ -494,12 +534,12 @@ free_with_user_data(void *data, void *user_data)
494534 * @return LY_ERR value.
495535 */
496536static LY_ERR
497- retrieve_schema_data (const char * mod_name , const char * mod_rev , const char * submod_name , const char * sub_rev ,
537+ retrieve_schema_data_imp (const char * mod_name , const char * mod_rev , const char * submod_name , const char * sub_rev ,
498538 void * user_data , LYS_INFORMAT * format , const char * * module_data ,
499539 void (* * free_module_data )(void * model_data , void * user_data ))
500540{
501541 struct clb_data_s * clb_data = (struct clb_data_s * )user_data ;
502- unsigned int u , v , match = 1 ;
542+ uint32_t u , v , match = 1 ;
503543 const char * name = NULL , * rev = NULL ;
504544 char * model_data = NULL ;
505545
@@ -519,7 +559,7 @@ retrieve_schema_data(const char *mod_name, const char *mod_rev, const char *subm
519559 if (!match ) {
520560 /* valid situation if we are retrieving YANG 1.1 schema and have only capabilities for now
521561 * (when loading ietf-datastore for ietf-yang-library) */
522- VRB (clb_data -> session , "Unable to identify revision of the schema \"%s\" from "
562+ VRB (clb_data -> session , "Unable to identify revision of the import schema \"%s\" from "
523563 "the available server side information." , mod_name );
524564 }
525565 }
@@ -530,15 +570,15 @@ retrieve_schema_data(const char *mod_name, const char *mod_rev, const char *subm
530570 } else if (match ) {
531571 if (!clb_data -> schemas [match - 1 ].submodules ) {
532572 VRB (clb_data -> session , "Unable to identify revision of the requested submodule \"%s\", "
533- "in schema \"%s\", from the available server side information." , submod_name , mod_name );
573+ "in import schema \"%s\", from the available server side information." , submod_name , mod_name );
534574 } else {
535575 for (v = 0 ; clb_data -> schemas [match - 1 ].submodules [v ].name ; ++ v ) {
536576 if (!strcmp (submod_name , clb_data -> schemas [match - 1 ].submodules [v ].name )) {
537577 rev = sub_rev = clb_data -> schemas [match - 1 ].submodules [v ].revision ;
538578 }
539579 }
540580 if (!rev ) {
541- ERR (clb_data -> session , "Requested submodule \"%s\" is not known for schema \"%s\" on server side." ,
581+ ERR (clb_data -> session , "Requested submodule \"%s\" is not found in import schema \"%s\" on server side." ,
542582 submod_name , mod_name );
543583 return LY_ENOTFOUND ;
544584 }
@@ -549,11 +589,10 @@ retrieve_schema_data(const char *mod_name, const char *mod_rev, const char *subm
549589 rev = mod_rev ;
550590 }
551591
552- VRB (clb_data -> session , "Retrieving data for schema \"%s\", revision \"%s\"." , name , rev ? rev : "<latest>" );
592+ VRB (clb_data -> session , "Retrieving data for import schema \"%s\", revision \"%s\"." , name , rev ? rev : "<latest>" );
553593
554594 if (match ) {
555- /* we have enough information to avoid communication with server and try to get
556- * the schema locally */
595+ /* we have enough information to avoid communication with server and try to get the schema locally */
557596
558597 /* 1. try to get data locally */
559598 model_data = retrieve_schema_data_localfile (name , rev , clb_data , format );
@@ -598,6 +637,7 @@ retrieve_schema_data(const char *mod_name, const char *mod_rev, const char *subm
598637 * @param[in] session NC session.
599638 * @param[in] name Schema name.
600639 * @param[in] revision Schema revision.
640+ * @param[in] features Enabled schema features.
601641 * @param[in] schemas Server schema info built from capabilities.
602642 * @param[in] user_clb User callback for retireving schema data.
603643 * @param[in] user_data User data for @p user_clb.
@@ -607,28 +647,33 @@ retrieve_schema_data(const char *mod_name, const char *mod_rev, const char *subm
607647 * @return -1 on error.
608648 */
609649static int
610- nc_ctx_load_module (struct nc_session * session , const char * name , const char * revision , struct schema_info * schemas ,
611- ly_module_imp_clb user_clb , void * user_data , int has_get_schema , struct lys_module * * mod )
650+ nc_ctx_load_module (struct nc_session * session , const char * name , const char * revision , const char * * features ,
651+ struct schema_info * schemas , ly_module_imp_clb user_clb , void * user_data , int has_get_schema , struct lys_module * * mod )
612652{
613653 int ret = 0 ;
614654 struct ly_err_item * eitem ;
615655 const char * module_data = NULL ;
656+ struct ly_in * in ;
616657 LYS_INFORMAT format ;
617658
618659 void (* free_module_data )(void * , void * ) = NULL ;
619660 struct clb_data_s clb_data ;
620661
621- * mod = NULL ;
662+ /* try to use a module from the context */
622663 if (revision ) {
623664 * mod = ly_ctx_get_module (session -> ctx , name , revision );
665+ } else {
666+ * mod = ly_ctx_get_module_implemented (session -> ctx , name );
667+ if (!* mod ) {
668+ * mod = ly_ctx_get_module_latest (session -> ctx , name );
669+ }
624670 }
671+
625672 if (* mod ) {
626- if (!(* mod )-> implemented ) {
627- /* make the present module implemented */
628- if (lys_set_implemented (* mod , NULL )) {
629- ERR (session , "Failed to implement model \"%s\"." , (* mod )-> name );
630- ret = -1 ;
631- }
673+ /* make the present module implemented and/or enable all its features */
674+ if (lys_set_implemented (* mod , features )) {
675+ ERR (session , "Failed to implement schema \"%s\"." , (* mod )-> name );
676+ ret = -1 ;
632677 }
633678 } else {
634679 /* missing implemented module, load it ... */
@@ -643,13 +688,16 @@ nc_ctx_load_module(struct nc_session *session, const char *name, const char *rev
643688 ly_log_options (LY_LOSTORE );
644689
645690 /* get module data */
646- retrieve_schema_data (name , revision , NULL , NULL , & clb_data , & format , & module_data , & free_module_data );
691+ retrieve_schema_data (name , revision , & clb_data , & format , & module_data , & free_module_data );
647692
648693 if (module_data ) {
649- /* parse the schema */
650- ly_ctx_set_module_imp_clb (session -> ctx , retrieve_schema_data , & clb_data );
694+ /* set import callback */
695+ ly_ctx_set_module_imp_clb (session -> ctx , retrieve_schema_data_imp , & clb_data );
651696
652- lys_parse_mem (session -> ctx , module_data , format , mod );
697+ /* parse the schema */
698+ ly_in_new_memory (module_data , & in );
699+ lys_parse (session -> ctx , in , format , features , mod );
700+ ly_in_free (in , 0 );
653701 if (* free_module_data ) {
654702 (* free_module_data )((char * )module_data , user_data );
655703 }
@@ -660,13 +708,13 @@ nc_ctx_load_module(struct nc_session *session, const char *name, const char *rev
660708 /* restore logging options, then print errors on definite failure */
661709 ly_log_options (LY_LOLOG | LY_LOSTORE_LAST );
662710 if (!(* mod )) {
663- for (eitem = ly_err_first (session -> ctx ); eitem && eitem -> next ; eitem = eitem -> next ) {
711+ for (eitem = ly_err_first (session -> ctx ); eitem ; eitem = eitem -> next ) {
664712 ly_err_print (session -> ctx , eitem );
665713 }
666714 ret = -1 ;
667715 } else {
668716 /* print only warnings */
669- for (eitem = ly_err_first (session -> ctx ); eitem && eitem -> next ; eitem = eitem -> next ) {
717+ for (eitem = ly_err_first (session -> ctx ); eitem ; eitem = eitem -> next ) {
670718 if (eitem -> level == LY_LLWRN ) {
671719 ly_err_print (session -> ctx , eitem );
672720 }
@@ -985,7 +1033,8 @@ nc_ctx_fill(struct nc_session *session, struct schema_info *modules, ly_module_i
9851033 }
9861034
9871035 /* we can continue even if it fails */
988- nc_ctx_load_module (session , modules [u ].name , modules [u ].revision , modules , user_clb , user_data , has_get_schema , & mod );
1036+ nc_ctx_load_module (session , modules [u ].name , modules [u ].revision , (const char * * )modules [u ].features , modules ,
1037+ user_clb , user_data , has_get_schema , & mod );
9891038
9901039 if (!mod ) {
9911040 if (session -> status != NC_STATUS_RUNNING ) {
@@ -998,9 +1047,6 @@ nc_ctx_fill(struct nc_session *session, struct schema_info *modules, ly_module_i
9981047 WRN (session , "Failed to load schema \"%s@%s\"." , modules [u ].name , modules [u ].revision ?
9991048 modules [u ].revision : "<latest>" );
10001049 session -> flags |= NC_SESSION_CLIENT_NOT_STRICT ;
1001- } else {
1002- /* set the features */
1003- lys_set_implemented (mod , (const char * * )modules [u ].features );
10041050 }
10051051 }
10061052
@@ -1027,29 +1073,41 @@ nc_ctx_fill_ietf_netconf(struct nc_session *session, struct schema_info *modules
10271073 void * user_data , int has_get_schema )
10281074{
10291075 uint32_t u ;
1076+ const char * * features = NULL ;
1077+ struct ly_in * in ;
10301078 struct lys_module * ietfnc ;
10311079
1080+ /* find supported features (capabilities) in ietf-netconf */
1081+ for (u = 0 ; modules [u ].name ; ++ u ) {
1082+ if (!strcmp (modules [u ].name , "ietf-netconf" )) {
1083+ assert (modules [u ].implemented );
1084+ features = (const char * * )modules [u ].features ;
1085+ break ;
1086+ }
1087+ }
1088+ if (!modules [u ].name ) {
1089+ ERR (session , "Base NETCONF schema not supported by the server." );
1090+ return -1 ;
1091+ }
1092+
10321093 ietfnc = ly_ctx_get_module_implemented (session -> ctx , "ietf-netconf" );
1033- if (!ietfnc ) {
1034- nc_ctx_load_module (session , "ietf-netconf" , NULL , modules , user_clb , user_data , has_get_schema , & ietfnc );
1094+ if (ietfnc ) {
1095+ /* make sure to enable all the features if already loaded */
1096+ lys_set_implemented (ietfnc , features );
1097+ } else {
1098+ /* load the module */
1099+ nc_ctx_load_module (session , "ietf-netconf" , NULL , features , modules , user_clb , user_data , has_get_schema , & ietfnc );
10351100 if (!ietfnc ) {
1036- lys_parse_mem (session -> ctx , ietf_netconf_2013_09_29_yang , LYS_IN_YANG , & ietfnc );
1101+ ly_in_new_memory (ietf_netconf_2013_09_29_yang , & in );
1102+ lys_parse (session -> ctx , in , LYS_IN_YANG , features , & ietfnc );
1103+ ly_in_free (in , 0 );
10371104 }
10381105 }
10391106 if (!ietfnc ) {
10401107 ERR (session , "Loading base NETCONF schema failed." );
10411108 return -1 ;
10421109 }
10431110
1044- /* set supported capabilities from ietf-netconf */
1045- for (u = 0 ; modules [u ].name ; ++ u ) {
1046- if (strcmp (modules [u ].name , "ietf-netconf" ) || !modules [u ].implemented ) {
1047- continue ;
1048- }
1049-
1050- lys_set_implemented (ietfnc , (const char * * )modules [u ].features );
1051- }
1052-
10531111 return 0 ;
10541112}
10551113
@@ -1127,15 +1185,15 @@ nc_ctx_check_and_fill(struct nc_session *session)
11271185 yanglib_support = 0 ;
11281186 } else {
11291187 revision = strndup (& revision [9 ], 10 );
1130- if (nc_ctx_load_module (session , "ietf-yang-library" , revision , server_modules , old_clb , old_data ,
1188+ if (nc_ctx_load_module (session , "ietf-yang-library" , revision , NULL , server_modules , old_clb , old_data ,
11311189 get_schema_support , & mod )) {
11321190 WRN (session , "Loading NETCONF ietf-yang-library schema failed, unable to use it to learn all "
11331191 "the supported modules." );
11341192 yanglib_support = 0 ;
11351193 }
11361194 if (strcmp (revision , "2019-01-04" ) >= 0 ) {
11371195 /* we also need ietf-datastores to be implemented */
1138- if (nc_ctx_load_module (session , "ietf-datastores" , NULL , server_modules , old_clb , old_data ,
1196+ if (nc_ctx_load_module (session , "ietf-datastores" , NULL , NULL , server_modules , old_clb , old_data ,
11391197 get_schema_support , & mod )) {
11401198 WRN (session , "Loading NETCONF ietf-datastores schema failed, unable to use yang-library "
11411199 "to learn all the supported modules." );
@@ -1145,10 +1203,12 @@ nc_ctx_check_and_fill(struct nc_session *session)
11451203 free (revision );
11461204
11471205 /* ietf-netconf-nmda is needed to issue get-data */
1148- if (!nc_ctx_load_module (session , "ietf-netconf-nmda" , NULL , server_modules , old_clb , old_data ,
1206+ if (!nc_ctx_load_module (session , "ietf-netconf-nmda" , NULL , NULL , server_modules , old_clb , old_data ,
11491207 get_schema_support , & mod )) {
1150- VRB (session , "Support for <get-data> from ietf-netcon -nmda found." );
1208+ VRB (session , "Support for <get-data> from ietf-netconf -nmda found." );
11511209 get_data_support = 1 ;
1210+ } else {
1211+ VRB (session , "Support for <get-data> from ietf-netconf-nmda not found." );
11521212 }
11531213 }
11541214 }
0 commit comments