1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
24 #include "core/session.h"
29 //private variables for context state
30 struct lys_ident_with_childcount {
31 struct lys_ident *ident;
34 static struct lys_ident_with_childcount *identities;
35 static int identities_size; //number of found identities
37 struct features_with_info {
41 static struct features_with_info *features;
42 static int features_size;
46 static bool check_identity_of_type(const struct lys_ident *ident, const struct lys_ident *type);
47 static int identity_get_id(const struct lys_ident *ident);
49 int context_init(const struct ly_ctx *ly_ctx) {
50 log_add_verbose(2, "context_init() begin\n");
58 log_add_verbose(2, "loading modules\n");
60 struct lys_module *module;
61 while((module = (struct lys_module *)ly_ctx_get_module_iter(ly_ctx, &idx)) != 0) {
62 log_add_verbose(2, "MODULE %s\n", module->name);
63 log_add_verbose(2, " prefix: %s\n", module->prefix);
64 log_add_verbose(2, " namespace: %s\n", module->ns);
65 log_add_verbose(2, " imports [%d]", module->imp_size);
66 if(module->imp_size) {
68 for(int i = 0; i < module->imp_size; i++) {
69 log_add(2, "%s(%s), ", module->imp[i].module->name, module->imp[i].module->prefix);
73 log_add_verbose(2, " implemented: %d\n", module->implemented);
75 if(module->implemented) {
76 log_add_verbose(2, " IDENT count: %d\n", module->ident_size);
77 if(module->ident_size) {
78 //add to list of identities
79 identities = (struct lys_ident_with_childcount *)realloc(identities, sizeof(struct lys_ident_with_childcount) * (identities_size + module->ident_size));
81 log_error("bad realloc\n");
85 for(int i = 0; i < module->ident_size; i++) {
86 identities[identities_size].ident = &module->ident[i];
87 identities[identities_size].children = 0;
90 if(module->ident[i].base_size) {
91 log_add_verbose(2, " IDENT[%d] %s with base %s:%s\n", i, module->ident[i].name, module->ident[i].base[0]->module->name, module->ident[i].base[0]->name);
92 int id = identity_get_id(module->ident[i].base[0]);
94 identities[id].children++;
98 log_add_verbose(2, " IDENT[%d] %s as base\n", i, module->ident[i].name);
104 log_add_verbose(2, " FEATURES count: %d\n", module->features_size);
105 if(module->features_size) {
106 //add to list of features
107 features = (struct features_with_info *)realloc(features, sizeof(struct features_with_info) * (features_size + module->features_size));
109 log_error("bad realloc\n");
113 for(int i = 0; i < module->features_size; i++) {
114 asprintf(&features[features_size].name, "%s:%s", module->name, module->features[i].name);
115 features[features_size].enabled = (lys_features_state(module, module->features[i].name) == 1);
116 log_add_verbose(2, " FEATURE[%d] %s iffeature_size=%d enabled=%d\n", i, module->features[i].name, module->features[i].iffeature_size, features[features_size].enabled);
122 log_add_verbose(2, "-> module not implemented, skipping...\n");
125 log_add_verbose(2, " ----\n");
128 log_add_verbose(2, "context_init() finished\n");
133 void context_free(void) {
134 log_add_verbose(2, "context_free()... ");
138 for(int i = 0; i < features_size; i++) {
139 free(features[i].name);
142 log_add(2, "done\n");
145 int context_get_identity_leafs_of_type(const struct lys_ident *ident, struct lys_ident ***found) {
147 *found = (struct lys_ident **)malloc(sizeof(struct lys_ident *) * identities_size);
149 log_error("bad malloc\n");
153 for(int i = 0; i < identities_size; i++) {
154 if(check_identity_of_type(identities[i].ident, ident)) {
155 if(identities[i].children == 0) {
156 (*found)[count] = identities[i].ident;
163 log_error("no identities found\n");
166 *found = (struct lys_ident **)realloc(*found, sizeof(struct lys_ident *) * count);
172 int context_get_features(char ***found_features) {
173 char **ftrs = (char **)malloc(sizeof(char *) * features_size);
175 log_error("could not alloc\n");
179 for(int i = 0; i < features_size; i++) {
180 ftrs[i] = (char *)malloc(sizeof(char) * (strlen(features[i].name) + 1));
182 log_error("could not alloc\n");
186 strcpy(ftrs[i], features[i].name);
189 *found_features = ftrs;
190 return features_size;
193 bool context_get_feature_enabled(const char *feature) {
194 for(int i = 0; i < features_size; i++) {
195 if(strcmp(feature, features[i].name) == 0) {
196 return features[i].enabled;
202 bool context_feature_enable(const char *feature) {
213 while((i < strlen(feature)) && (feature[i] != ':')) {
222 while(i < strlen(feature)) {
223 feat[j] = feature[i];
230 if((rc = sr_enable_module_feature(session_connection, mod, feat)) != SR_ERR_OK) {
237 bool context_module_install(const char *name, const char *path) {
241 char *searchpath = strdup(path);
242 int rc = sr_install_module(session_connection, path, dirname(searchpath), 0, 0);
244 if(rc != SR_ERR_OK) {
245 /* succeed if the module is already installed */
246 if(rc != SR_ERR_EXISTS) {
251 char *data_path = str_replace(path, ".yang", ".xml");
252 if(file_exists(data_path)) {
253 rc = sr_install_module_data(session_connection, name, 0, data_path, LYD_XML);
254 if(rc != SR_ERR_OK) {
255 log_add(1, " xml error ");
256 sr_remove_module(session_connection, name);
257 context_apply_changes();
263 data_path = str_replace(path, ".yang", ".json");
264 if(file_exists(data_path)) {
265 rc = sr_install_module_data(session_connection, name, 0, data_path, LYD_JSON);
266 if(rc != SR_ERR_OK) {
267 log_add(1, " json error ");
268 sr_remove_module(session_connection, name);
269 context_apply_changes();
276 if(!context_apply_changes()) {
277 sr_remove_module(session_connection, name);
278 context_apply_changes();
285 bool context_module_set_access(const char *module_name) {
288 if(sr_set_module_access(session_connection, module_name, "root", "root", 0666) != SR_ERR_OK) {
295 bool context_apply_changes(void) {
297 uint32_t connection_count = 0;
300 sr_disconnect(session_connection);
301 session_connection = 0;
303 /* get connection count */
304 if((rc = sr_connection_count(&connection_count)) != SR_ERR_OK) {
305 log_error("sr_connection_count() failed to get connection count\n");
309 if(connection_count) {
310 log_error("cannot apply changes because of existing connections\n");
314 if((rc = sr_connect(SR_CONN_ERR_ON_SCHED_FAIL, &session_connection)) != SR_ERR_OK) {
315 if((rc = sr_connect(0, &session_connection)) != SR_ERR_OK) {
316 log_error("failed to reconnect to sysrepo\n");
322 session_context = (struct ly_ctx *)sr_get_context(session_connection);
323 if(session_context == 0) {
324 log_error("sr_get_context failed\n");
331 bool context_yang_is_module(const char *path) {
335 struct ly_ctx *ctx = ly_ctx_new(0, 0);
337 log_error("ly_ctx_new failed\n");
340 char *searchpath = strdup(path);
341 ly_ctx_set_searchdir(ctx, dirname(searchpath));
342 const struct lys_module *mod = lys_parse_path(ctx, path, LYS_YANG);
343 if((!mod) && (ly_vecode(ctx) == LYVE_SUBMODULE)) {
348 ly_ctx_destroy(ctx, 0);
353 static bool check_identity_of_type(const struct lys_ident *ident, const struct lys_ident *type) {
356 if((ident->name == type->name) && (ident->module->name == type->module->name)) {
359 else if(ident->base_size != 0) {
361 for(int i = 0; i < ident->base_size; i++) {
362 result |= check_identity_of_type(ident->base[i], type);
372 static int identity_get_id(const struct lys_ident *ident) {
375 for(int i = 0; i < identities_size; i++) {
376 if((ident->name == identities[i].ident->name) && (ident->module->name == identities[i].ident->module->name)) {