/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_ssh_n_auth_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL, *ptr, *msg; uint16_t num; if (op & XMLDIFF_REM) { netopeer_options.ssh_opts->auth_timeout = 10; return EXIT_SUCCESS; } content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } num = strtol(content, &ptr, 10); if (*ptr != '\0') { *error = nc_err_new(NC_ERR_OP_FAILED); if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) { nc_err_set(*error, NC_ERR_PARAM_MSG, msg); free(msg); } return EXIT_FAILURE; } netopeer_options.ssh_opts->auth_timeout = num; return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_hello_timeout(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL, *ptr, *msg; uint32_t num; if (op & XMLDIFF_REM) { /* set default value */ nc_hello_timeout(600 * 1000); return EXIT_SUCCESS; } content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } num = strtol(content, &ptr, 10); if (*ptr != '\0') { *error = nc_err_new(NC_ERR_BAD_ELEM); if (asprintf(&msg, "Could not convert '%s' to a number.", content) == 0) { nc_err_set(*error, NC_ERR_PARAM_MSG, msg); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/hello-timeout"); free(msg); } return EXIT_FAILURE; } nc_hello_timeout(num * 1000); return EXIT_SUCCESS; }
int ofcds_deleteconfig(void *UNUSED(data), NC_DATASTORE target, struct nc_err **error) { switch (target) { case NC_DATASTORE_RUNNING: *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Cannot delete a running datastore."); return EXIT_FAILURE; case NC_DATASTORE_STARTUP: store_rollback(gds_startup, NC_DATASTORE_STARTUP); gds_startup = NULL; break; case NC_DATASTORE_CANDIDATE: store_rollback(gds_cand, NC_DATASTORE_CANDIDATE); gds_cand = NULL; break; default: nc_verb_error("Invalid <delete-config> target."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target"); return EXIT_FAILURE; } return EXIT_SUCCESS; }
nc_reply* rpc_reload_module(xmlNodePtr input) { xmlNodePtr module_node = get_rpc_node("module", input); char* module_name; struct np_module* module = netopeer_options.modules; if (module_node) { module_name = (char*)xmlNodeGetContent(module_node); } else { return nc_reply_error(nc_err_new(NC_ERR_MISSING_ELEM)); } while (module) { if (strcmp(module->name, module_name) == 0) { break; } module = module->next; } free(module_name); if (module == NULL) { return nc_reply_error(nc_err_new(NC_ERR_INVALID_VALUE)); } if (module_disable(module, 0) || module_enable(module, 0)) { return nc_reply_error(nc_err_new(NC_ERR_OP_FAILED)); } return nc_reply_ok(); }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_max_sessions(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL, *ptr, *msg; uint16_t num; if (op & XMLDIFF_REM) { netopeer_options.max_sessions = 8; return EXIT_SUCCESS; } content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } num = strtol(content, &ptr, 10); if (*ptr != '\0') { asprintf(&msg, "Could not convert '%s' to a number.", content); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_MSG, msg); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/max-sessions"); free(msg); return EXIT_FAILURE; } netopeer_options.max_sessions = num; return EXIT_SUCCESS; }
int ofcds_unlock(void *UNUSED(data), NC_DATASTORE target, const char *session_id, struct nc_err **error) { int *locked; char **sid; switch (target) { case NC_DATASTORE_RUNNING: locked = &(locks.running); sid = &(locks.running_sid); break; case NC_DATASTORE_STARTUP: locked = &(locks.startup); sid = &(locks.startup_sid); break; case NC_DATASTORE_CANDIDATE: locked = &(locks.cand); sid = &(locks.cand_sid); break; default: /* handled by libnetconf */ return EXIT_FAILURE; } if (*locked) { if (strcmp(*sid, session_id) == 0) { /* correct request, unlock */ *locked = 0; free(*sid); *sid = NULL; nc_verb_verbose("OFC datastore %d unlocked by %s.", target, session_id); } else { /* locked by another session */ *error = nc_err_new(NC_ERR_LOCK_DENIED); nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is locked by another session."); return EXIT_FAILURE; } } else { /* not locked */ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is not locked."); return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_tls_n_server_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* key = NULL, *type = NULL; xmlNodePtr child; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { for (child = new_node->children; child != NULL; child = child->next) { if (xmlStrEqual(child->name, BAD_CAST "key-data")) { key = get_node_content(child); } if (xmlStrEqual(child->name, BAD_CAST "key-type")) { type = get_node_content(child); } } if (key == NULL || type == NULL) { *error = nc_err_new(NC_ERR_MISSING_ELEM); nc_err_set(*error, NC_ERR_PARAM_MSG, "key-data and/or key-type element missing."); return EXIT_FAILURE; } if (strcmp(type, "RSA") != 0 && strcmp(type, "DSA") != 0) { *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/server-key/key-type"); return EXIT_FAILURE; } } /* TLS_CTX LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock); free(netopeer_options.tls_opts->server_key); netopeer_options.tls_opts->server_key = NULL; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { netopeer_options.tls_opts->server_key = strdup(key); if (strcmp(type, "RSA") == 0) { netopeer_options.tls_opts->server_key_type = 1; } else { netopeer_options.tls_opts->server_key_type = 0; } } netopeer_options.tls_opts->tls_ctx_change_flag = 1; /* TLS_CTX UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock); return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_tls_n_crl_dir(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } } /* CRL_DIR LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->crl_dir_lock); free(netopeer_options.tls_opts->crl_dir); netopeer_options.tls_opts->crl_dir = NULL; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { netopeer_options.tls_opts->crl_dir = strdup(content); } /* CRL_DIR UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->crl_dir_lock); return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_tls_n_server_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } } /* TLS_CTX LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock); free(netopeer_options.tls_opts->server_cert); netopeer_options.tls_opts->server_cert = NULL; if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { netopeer_options.tls_opts->server_cert = strdup(content); } netopeer_options.tls_opts->tls_ctx_change_flag = 1; /* TLS_CTX UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock); return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_tls_n_trusted_ca_certs_n_trusted_ca_cert(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) { char* content = NULL; if (op & (XMLDIFF_REM | XMLDIFF_MOD)) { content = get_node_content(old_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } /* TLS_CTX LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock); if (del_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0) != 0) { nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__); } else { netopeer_options.tls_opts->tls_ctx_change_flag = 1; } /* TLS_CTX UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock); } if (op & (XMLDIFF_MOD | XMLDIFF_ADD)) { content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } /* TLS_CTX LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->tls_ctx_lock); add_trusted_cert(&netopeer_options.tls_opts->trusted_certs, content, 0); netopeer_options.tls_opts->tls_ctx_change_flag = 1; /* TLS_CTX UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->tls_ctx_lock); } return EXIT_SUCCESS; }
nc_reply* rpc_netopeer_reboot(xmlNodePtr input) { xmlNodePtr type_node = get_rpc_node("type", input); char* type_str = NULL; if (type_node) { type_str = (char*)xmlNodeGetContent(type_node); } if (type_str == NULL || strcmp(type_str, "soft") == 0) { restart_soft = 1; } else if (strcmp(type_str, "hard") == 0) { quit = 1; restart_hard = 1; } else { free(type_str); return nc_reply_error(nc_err_new(NC_ERR_INVALID_VALUE)); } free(type_str); return nc_reply_ok(); }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_ssh_n_password_auth_enabled(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL; if (op & XMLDIFF_REM) { netopeer_options.ssh_opts->password_auth_enabled = 1; return EXIT_SUCCESS; } content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } if (strcmp(content, "false") == 0) { netopeer_options.ssh_opts->password_auth_enabled = 0; } else { netopeer_options.ssh_opts->password_auth_enabled = 1; } return EXIT_SUCCESS; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_ssh_n_server_keys_n_dsa_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr UNUSED(old_node), xmlNodePtr new_node, struct nc_err** error) { char* content = NULL; if (op & XMLDIFF_REM) { free(netopeer_options.ssh_opts->dsa_key); netopeer_options.ssh_opts->dsa_key = NULL; netopeer_options.ssh_opts->server_key_change_flag = 1; return EXIT_SUCCESS; } content = get_node_content(new_node); if (content == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: node content missing", __func__); return EXIT_FAILURE; } free(netopeer_options.ssh_opts->dsa_key); netopeer_options.ssh_opts->dsa_key = strdup(content); netopeer_options.ssh_opts->server_key_change_flag = 1; return EXIT_SUCCESS; }
int ofcds_lock(void *UNUSED(data), NC_DATASTORE target, const char *session_id, struct nc_err **error) { int *locked; char **sid; switch (target) { case NC_DATASTORE_RUNNING: locked = &(locks.running); sid = &(locks.running_sid); break; case NC_DATASTORE_STARTUP: locked = &(locks.startup); sid = &(locks.startup_sid); break; case NC_DATASTORE_CANDIDATE: locked = &(locks.cand); sid = &(locks.cand_sid); break; default: /* handled by libnetconf */ return EXIT_FAILURE; } if (*locked) { /* datastore is already locked */ *error = nc_err_new(NC_ERR_LOCK_DENIED); nc_err_set(*error, NC_ERR_PARAM_INFO_SID, *sid); return EXIT_FAILURE; } else { /* remember the lock */ *locked = 1; *sid = strdup(session_id); nc_verb_verbose("OFC datastore %d locked by %s.", target, session_id); } return EXIT_SUCCESS; }
/** * @brief Parse the given reply message and create a NETCONF error structure * describing the error from the reply. Reply must be of the #NC_REPLY_ERROR type. * @param[in] reply \<rpc-reply\> message to be parsed. * @return Filled error structure according to the given rpc-reply, it is up to the * caller to free the structure using nc_err_free(). */ struct nc_err* nc_err_parse(nc_reply* reply) { xmlXPathObjectPtr result = NULL; xmlNodePtr node, subnode; int i; struct nc_err* e = NULL, *eaux = NULL; if (reply == NULL || reply->doc == NULL || reply->type.reply != NC_REPLY_ERROR) { return (NULL); } if (reply->error != NULL) { /* error structure is already created */ return (reply->error); } /* find all <rpc-error>s */ result = xmlXPathEvalExpression(BAD_CAST "/"NC_NS_BASE10_ID":rpc-reply/"NC_NS_BASE10_ID":rpc-error", reply->ctxt); if (result != NULL) { for (i = 0; i < result->nodesetval->nodeNr; i++) { /* error structure is not yet created */ eaux = nc_err_new(NC_ERR_EMPTY); /* parse the content of the message */ for (node = result->nodesetval->nodeTab[i]->children; node != NULL; node = node->next) { if (node->type != XML_ELEMENT_NODE || node->ns == NULL || strcmp(NC_NS_BASE10, (char*)(node->ns->href)) != 0) { continue; } if (xmlStrcmp(node->name, BAD_CAST "error-tag") == 0) { eaux->tag = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-type") == 0) { eaux->type = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-severity") == 0) { eaux->severity = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-app-tag") == 0) { eaux->apptag = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-path") == 0) { eaux->path = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-message") == 0) { eaux->message = (char*) xmlNodeGetContent(node); } else if (xmlStrcmp(node->name, BAD_CAST "error-info") == 0) { subnode = node->children; while (subnode != NULL) { if (subnode->type != XML_ELEMENT_NODE || subnode->ns == NULL || strcmp(NC_NS_BASE10, (char*)(subnode->ns->href)) != 0) { subnode = subnode->next; continue; } if (xmlStrcmp(subnode->name, BAD_CAST "bad-attribute") == 0) { eaux->attribute = (char*) xmlNodeGetContent(subnode); } else if (xmlStrcmp(subnode->name, BAD_CAST "bad-element") == 0 || xmlStrcmp(subnode->name, BAD_CAST "ok-element") == 0 || xmlStrcmp(subnode->name, BAD_CAST "err-element") == 0 || xmlStrcmp(subnode->name, BAD_CAST "noop-element") == 0) { eaux->element = (char*) xmlNodeGetContent(subnode); } else if (xmlStrcmp(subnode->name, BAD_CAST "bad-namespace") == 0) { eaux->ns = (char*) xmlNodeGetContent(subnode); } else if (xmlStrcmp(subnode->name, BAD_CAST "session-id") == 0) { eaux->sid = (char*) xmlNodeGetContent(subnode); } subnode = subnode->next; } } } if (e != NULL) { /* concatenate multiple rpc-errors in repl-reply */ eaux->next = e; } e = eaux; } xmlXPathFreeObject(result); } else { ERROR("No error information in the reply message to parse."); /* NULL, which is default e's value, will be returned */ } /* store the result for the further use */ //reply->error = nc_err_dup(e); reply->error = e; return (e); }
static PyObject *ncProcessRPC(ncSessionObject *self) { NC_MSG_TYPE ret; NC_RPC_TYPE req_type; NC_OP req_op; nc_rpc *rpc = NULL; nc_reply *reply = NULL; struct nc_err* e = NULL; SESSION_CHECK(self); /* receive incoming message */ ret = nc_session_recv_rpc(self->session, -1, &rpc); if (ret != NC_MSG_RPC) { if (nc_session_get_status(self->session) != NC_SESSION_STATUS_WORKING) { /* something really bad happend, and communication is not possible anymore */ nc_session_free(self->session); self->session = NULL; } Py_RETURN_NONE; } /* process it */ req_type = nc_rpc_get_type(rpc); req_op = nc_rpc_get_op(rpc); if (req_type == NC_RPC_SESSION) { /* process operations affectinf session */ switch(req_op) { case NC_OP_CLOSESESSION: /* exit the event loop immediately without processing any following request */ reply = nc_reply_ok(); break; case NC_OP_KILLSESSION: /* todo: kill the requested session */ reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED)); break; default: reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED)); break; } } else if (req_type == NC_RPC_DATASTORE_READ) { /* process operations reading datastore */ switch (req_op) { case NC_OP_GET: case NC_OP_GETCONFIG: reply = ncds_apply_rpc2all(self->session, rpc, NULL); break; default: reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED)); break; } } else if (req_type == NC_RPC_DATASTORE_WRITE) { /* process operations affecting datastore */ switch (req_op) { case NC_OP_LOCK: case NC_OP_UNLOCK: case NC_OP_COPYCONFIG: case NC_OP_DELETECONFIG: case NC_OP_EDITCONFIG: reply = ncds_apply_rpc2all(self->session, rpc, NULL); break; default: reply = nc_reply_error(nc_err_new(NC_ERR_OP_NOT_SUPPORTED)); break; } } else { /* process other operations */ reply = ncds_apply_rpc2all(self->session, rpc, NULL); } /* create reply */ if (reply == NULL) { reply = nc_reply_error(nc_err_new(NC_ERR_OP_FAILED)); } else if (reply == NCDS_RPC_NOT_APPLICABLE) { e = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(e, NC_ERR_PARAM_MSG, "Requested operation cannot be performed on the managed datastore."); reply = nc_reply_error(e); } /* and send the reply to the client */ nc_session_send_reply(self->session, rpc, reply); nc_rpc_free(rpc); nc_reply_free(reply); if (req_op == NC_OP_CLOSESESSION) { /* free the Session */ nc_session_free(self->session); self->session = NULL; } Py_RETURN_NONE; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_tls_n_cert_maps_n_cert_to_name(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) { char* id = NULL, *fingerprint = NULL, *map_type = NULL, *name = NULL, *ptr, *msg; xmlNodePtr child; callback_restart: for (child = (op & (XMLDIFF_MOD | XMLDIFF_REM) ? old_node->children : new_node->children); child != NULL; child = child->next) { if (xmlStrEqual(child->name, BAD_CAST "id")) { id = get_node_content(child); } if (xmlStrEqual(child->name, BAD_CAST "fingerprint")) { fingerprint = get_node_content(child); } if (xmlStrEqual(child->name, BAD_CAST "map-type")) { map_type = get_node_content(child); if (strchr(map_type, ':') != NULL) { map_type = strchr(map_type, ':')+1; } } if (xmlStrEqual(child->name, BAD_CAST "name")) { name = get_node_content(child); } } if (id == NULL || fingerprint == NULL || map_type == NULL) { *error = nc_err_new(NC_ERR_MISSING_ELEM); nc_err_set(*error, NC_ERR_PARAM_MSG, "id and/or fingerprint and/or map-type element missing."); return EXIT_FAILURE; } strtol(id, &ptr, 10); if (*ptr != '\0') { asprintf(&msg, "Could not convert '%s' to a number.", id); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "/netopeer/tls/cert-maps/cert-to-name/id"); nc_err_set(*error, NC_ERR_PARAM_MSG, msg); free(msg); return EXIT_FAILURE; } if (strcmp(map_type, "specified") == 0 && name == NULL) { *error = nc_err_new(NC_ERR_MISSING_ELEM); nc_err_set(*error, NC_ERR_PARAM_MSG, "name element missing."); return EXIT_FAILURE; } /* CTN_MAP LOCK */ pthread_mutex_lock(&netopeer_options.tls_opts->ctn_map_lock); if (op & (XMLDIFF_REM | XMLDIFF_MOD)) { if (del_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name) != 0) { nc_verb_error("%s: inconsistent state (%s:%d)", __func__, __FILE__, __LINE__); } if (op & XMLDIFF_MOD) { /* CTN_MAP UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock); op = XMLDIFF_ADD; goto callback_restart; } } if (op & XMLDIFF_ADD) { add_ctn_item(&netopeer_options.tls_opts->ctn_map, atoi(id), fingerprint, ctn_type_parse(map_type), name); } /* CTN_MAP UNLOCK */ pthread_mutex_unlock(&netopeer_options.tls_opts->ctn_map_lock); return EXIT_SUCCESS; }
int ofcds_editconfig(void *UNUSED(data), const nc_rpc * UNUSED(rpc), NC_DATASTORE target, const char *config, NC_EDIT_DEFOP_TYPE defop, NC_EDIT_ERROPT_TYPE UNUSED(errop), struct nc_err **error) { int ret = EXIT_FAILURE, running = 0; char *aux; int cfgds_new = 0; xmlDocPtr cfgds = NULL, cfg = NULL, cfg_clone = NULL; xmlNodePtr rootcfg; if (defop == NC_EDIT_DEFOP_NOTSET) { defop = NC_EDIT_DEFOP_MERGE; } cfg = xmlReadMemory(config, strlen(config), NULL, NULL, XML_READ_OPT); rootcfg = xmlDocGetRootElement(cfg); if (!cfg || (rootcfg && !xmlStrEqual(rootcfg->name, BAD_CAST "capable-switch"))) { nc_verb_error("Invalid <edit-config> configuration data."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config"); return EXIT_FAILURE; } switch (target) { case NC_DATASTORE_RUNNING: /* Make a copy of parsed config - we will find port/configuration in * it. It is used after txn_commit(). */ cfg_clone = xmlCopyDoc(cfg, 1); aux = ofc_get_config_data(); if (!aux) { *error = nc_err_new(NC_ERR_OP_FAILED); goto error_cleanup; } cfgds = xmlReadMemory(aux, strlen(aux), NULL, NULL, XML_READ_OPT); free(aux); running = 1; break; case NC_DATASTORE_STARTUP: cfgds = gds_startup; break; case NC_DATASTORE_CANDIDATE: cfgds = gds_cand; break; default: nc_verb_error("Invalid <edit-config> target."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target"); goto error_cleanup; } store_rollback(xmlCopyDoc(cfgds, 1), target); /* check keys in config's lists */ ret = check_keys(cfg, error); if (ret != EXIT_SUCCESS) { goto error_cleanup; } /* check operations */ ret = check_edit_ops(NC_EDIT_OP_DELETE, defop, cfgds, cfg, error); if (ret != EXIT_SUCCESS) { goto error_cleanup; } ret = check_edit_ops(NC_EDIT_OP_CREATE, defop, cfgds, cfg, error); if (ret != EXIT_SUCCESS) { goto error_cleanup; } if (target == NC_DATASTORE_RUNNING) { txn_init(); } ret = compact_edit_operations(cfg, defop); if (ret != EXIT_SUCCESS) { nc_verb_error("Compacting edit-config operations failed."); if (error != NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); } goto error_cleanup; } /* perform operations */ if (!cfgds) { cfgds_new = 1; cfgds = xmlNewDoc(BAD_CAST "1.0"); } ret = edit_operations(cfgds, cfg, defop, running, error); if (ret != EXIT_SUCCESS) { goto error_cleanup; } /* with defaults capability */ if (ncdflt_get_basic_mode() == NCWD_MODE_TRIM) { /* server work in trim basic mode and therefore all default values * must be removed from the datastore. */ /* TODO */ } if (target == NC_DATASTORE_RUNNING) { ret = txn_commit(error); if (ret == EXIT_SUCCESS) { /* modify port/configuration of ports that were created */ ret = of_post_ports(xmlDocGetRootElement(cfg_clone), error); } /* config clone was used and it is not needed by now */ xmlFreeDoc(cfg_clone); xmlFreeDoc(cfgds); } else if (cfgds_new){ if (cfgds->children) { /* document changed, because we started with empty document */ if (target == NC_DATASTORE_STARTUP) { gds_startup = cfgds; cfgds = NULL; } else if (target == NC_DATASTORE_CANDIDATE) { gds_cand = cfgds; cfgds = NULL; } } xmlFreeDoc(cfgds); } xmlFreeDoc(cfg); return ret; error_cleanup: if (target == NC_DATASTORE_RUNNING) { txn_abort(); xmlFreeDoc(cfg_clone); xmlFreeDoc(cfgds); } xmlFreeDoc(cfg); return ret; }
int ofcds_copyconfig(void *UNUSED(data), NC_DATASTORE target, NC_DATASTORE source, char *config, struct nc_err **error) { int ret = EXIT_FAILURE; char *s; xmlDocPtr src_doc = NULL; xmlDocPtr dst_doc = NULL; xmlNodePtr root; static const char *ds[] = {"error", "<config>", "URL", "running", "startup", "candidate"}; nc_verb_verbose("OFC COPY-CONFIG (from %s to %s)", ds[source], ds[target]); switch (source) { case NC_DATASTORE_RUNNING: s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error); if (!s) { nc_verb_error ("copy-config: unable to get running source repository"); return EXIT_FAILURE; } src_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT); free(s); if (!src_doc) { nc_verb_error("copy-config: invalid running source data"); *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "invalid running source data"); return EXIT_FAILURE; } break; case NC_DATASTORE_STARTUP: src_doc = xmlCopyDoc(gds_startup, 1); break; case NC_DATASTORE_CANDIDATE: src_doc = xmlCopyDoc(gds_cand, 1); break; case NC_DATASTORE_CONFIG: if (config && strlen(config) > 0) { src_doc = xmlReadMemory(config, strlen(config), NULL, NULL, XML_READ_OPT); } if (!config || (strlen(config) > 0 && !src_doc)) { nc_verb_error("Invalid source configuration data."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config"); return EXIT_FAILURE; } break; default: nc_verb_error("Invalid <get-config> source."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source"); return EXIT_FAILURE; } switch (target) { case NC_DATASTORE_RUNNING: /* apply source to OVSDB */ s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error); if (!s) { nc_verb_error("copy-config: unable to get running source data"); goto cleanup; } dst_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT); free(s); root = xmlDocGetRootElement(src_doc); if (!dst_doc) { /* create envelope */ dst_doc = xmlNewDoc(BAD_CAST "1.0"); } if (!rollbacking) { store_rollback(xmlCopyDoc(dst_doc, 1), target); } txn_init(); if (edit_replace(dst_doc, root, 1, error)) { txn_abort(); } else { ret = txn_commit(error); } xmlFreeDoc(dst_doc); goto cleanup; break; case NC_DATASTORE_STARTUP: case NC_DATASTORE_CANDIDATE: /* create copy */ if (src_doc) { dst_doc = src_doc; src_doc = NULL; } /* store the copy */ if (target == NC_DATASTORE_STARTUP) { if (!rollbacking) { store_rollback(gds_startup, target); } else { xmlFreeDoc(gds_startup); } gds_startup = dst_doc; } else { /* NC_DATASTORE_CANDIDATE */ if (!rollbacking) { store_rollback(gds_cand, target); } else { xmlFreeDoc(gds_cand); } gds_cand = dst_doc; } break; default: nc_verb_error("Invalid <get-config> source."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source"); goto cleanup; } ret = EXIT_SUCCESS; cleanup: xmlFreeDoc(src_doc); return ret; }
/* !DO NOT ALTER FUNCTION SIGNATURE! */ int callback_n_netopeer_n_ssh_n_client_auth_keys_n_client_auth_key(void** UNUSED(data), XMLDIFF_OP op, xmlNodePtr old_node, xmlNodePtr new_node, struct nc_err** error) { xmlNodePtr node; char* path = NULL, *username = NULL; struct np_auth_key* key; if (op & XMLDIFF_REM) { node = old_node; } else { node = new_node; } for (node = node->children; node != NULL; node = node->next) { if (xmlStrEqual(node->name, BAD_CAST "path")) { path = get_node_content(node); } if (xmlStrEqual(node->name, BAD_CAST "username")) { username = get_node_content(node); } } if (path == NULL || username == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: path and/or username missing", __func__); return EXIT_FAILURE; } if (op & (XMLDIFF_REM | XMLDIFF_MOD)) { for (key = netopeer_options.ssh_opts->client_auth_keys; key != NULL; key = key->next) { if (strcmp(key->path, path) == 0) { break; } } if (key == NULL) { *error = nc_err_new(NC_ERR_OP_FAILED); nc_verb_error("%s: internal error: changed key not found", __func__); return EXIT_FAILURE; } /* CLIENT KEYS LOCK */ pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock); /* remove the key */ if (op & XMLDIFF_REM) { if (key->prev == NULL) { netopeer_options.ssh_opts->client_auth_keys = key->next; free(key->path); free(key->username); free(key); if (netopeer_options.ssh_opts->client_auth_keys != NULL) { netopeer_options.ssh_opts->client_auth_keys->prev = NULL; } } else { key->prev->next = key->next; if (key->next != NULL) { key->next->prev = key->prev; } free(key->path); free(key->username); free(key); } /* modify the key */ } else { free(key->username); key->username = strdup(username); } /* CLIENT KEYS UNLOCK */ pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock); } else if (op & XMLDIFF_ADD) { /* CLIENT KEYS LOCK */ pthread_mutex_lock(&netopeer_options.ssh_opts->client_keys_lock); /* add the key */ if (netopeer_options.ssh_opts->client_auth_keys == NULL) { netopeer_options.ssh_opts->client_auth_keys = calloc(1, sizeof(struct np_auth_key)); netopeer_options.ssh_opts->client_auth_keys->path = strdup(path); netopeer_options.ssh_opts->client_auth_keys->username = strdup(username); } else { for (key = netopeer_options.ssh_opts->client_auth_keys; key->next != NULL; key = key->next) { key->next = calloc(1, sizeof(struct np_auth_key)); key->path = strdup(path); key->username = strdup(username); key->next->prev = key; } } /* CLIENT KEYS UNLOCK */ pthread_mutex_unlock(&netopeer_options.ssh_opts->client_keys_lock); } return EXIT_SUCCESS; }
int ncds_custom_lock(struct ncds_ds* ds, const struct nc_session* session, NC_DATASTORE target, struct nc_err** error) { int retval, localinfo = 0; const char *sid = NULL; struct ncds_ds_custom *c_ds = (struct ncds_ds_custom *) ds; struct ncds_lockinfo *linfo; pthread_mutex_t* linfo_mut = NULL; linfo = get_lockinfo(target, &linfo_mut); if (linfo == NULL) { *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target"); return (EXIT_FAILURE); } pthread_mutex_lock(linfo_mut); if (c_ds->callbacks->is_locked == NULL) { /* is_locked() is not implemented by custom datastore, use local info */ localinfo = 1; if (linfo->sid != NULL) { /* datastore is already locked */ retval = 1; sid = linfo->sid; } else { retval = 0; } } else { /* take locking access into custom datastore plugin */ sem_wait(cds_lock); /* localinfo = 0 */ /* get current info using is_locked() */ retval = c_ds->callbacks->is_locked(c_ds->data, target, &sid, NULL); if (retval < 0) { /* error */ sem_post(cds_lock); pthread_mutex_unlock(linfo_mut); ERROR("%s: custom datastore's is_locked() function failed (error %d)", __func__, retval); *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "custom datastore's is_locked() function failed"); return (EXIT_FAILURE); } } /* check current status of the lock */ if (retval == 0 || localinfo) { /* datastore is not locked (or we are not sure), try to lock it */ retval = c_ds->callbacks->lock(c_ds->data, target, session->session_id, error); } else { /* retval == 1 && localinfo == 0 */ /* datastore is already locked */ *error = nc_err_new(NC_ERR_LOCK_DENIED); nc_err_set(*error, NC_ERR_PARAM_INFO_SID, sid); retval = EXIT_FAILURE; } /* drop locking access into custom datastore plugin */ if (localinfo == 0) { sem_post(cds_lock); } /* update localinfo structure */ if (retval == EXIT_SUCCESS) { linfo->time = nc_time2datetime(time(NULL), NULL); linfo->sid = strdup(session->session_id); } pthread_mutex_unlock(linfo_mut); return (retval); }
int ncds_custom_unlock(struct ncds_ds* ds, const struct nc_session* session, NC_DATASTORE target, struct nc_err** error) { int retval, localinfo = 0; const char *sid = NULL; struct ncds_ds_custom *c_ds = (struct ncds_ds_custom *) ds; struct ncds_lockinfo *linfo; pthread_mutex_t* linfo_mut = NULL; linfo = get_lockinfo(target, &linfo_mut); if (linfo == NULL) { *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target"); return (EXIT_FAILURE); } pthread_mutex_lock(linfo_mut); if (c_ds->callbacks->is_locked == NULL) { /* is_locked() is not implemented by custom datastore, so we will * try to use local info */ localinfo = 1; if (linfo->sid == NULL) { /* datastore is not locked */ retval = 0; } else { retval = 1; sid = linfo->sid; } } else { /* take locking access into custom datastore plugin */ sem_wait(cds_lock); /* localinfo = 0 */ /* get current info using is_locked() */ retval = c_ds->callbacks->is_locked(c_ds->data, target, &sid, NULL); if (retval < 0) { /* error */ sem_post(cds_lock); pthread_mutex_unlock(linfo_mut); ERROR("%s: custom datastore's is_locked() function failed (error %d)", __func__, retval); *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "custom datastore's is_locked() function failed"); return (EXIT_FAILURE); } } if (retval == 0) { if (localinfo) { /* try to call custom's unlock() if our info was up-to-date */ retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error); /* if unlock succeeded, we were wrong and operation succeeds */ } else { /* datastore is not locked */ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is not locked."); retval = EXIT_FAILURE; } } else { /* retval == 1 */ /* datastore is locked, check that we can unlock it and do it */ if (strcmp(sid, session->session_id) != 0) { if (localinfo) { /* try to call custom's unlock() if our info was up-to-date */ retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error); /* if unlock succeeded, we were wrong and operation succeeds */ } else { /* datastore is locked by someone else */ *error = nc_err_new(NC_ERR_OP_FAILED); nc_err_set(*error, NC_ERR_PARAM_MSG, "Target datastore is locked by another session."); retval = EXIT_FAILURE; } } else { /* try to unlock the datastore */ retval = c_ds->callbacks->unlock(c_ds->data, target, session->session_id, error); } } /* drop locking access into custom datastore plugin */ if (localinfo == 0) { sem_post(cds_lock); } if (retval == EXIT_SUCCESS) { free(linfo->time); free(linfo->sid); linfo->time = NULL; linfo->sid = NULL; } pthread_mutex_unlock(linfo_mut); return (retval); }
char * ofcds_getconfig(void *UNUSED(data), NC_DATASTORE target, struct nc_err **error) { xmlChar *config_data = NULL; switch (target) { case NC_DATASTORE_RUNNING: /* If there is no id of the capable-switch (no configuration data were * provided), continue as there is no OVSDB */ return ofc_get_config_data(); case NC_DATASTORE_STARTUP: if (!gds_startup) { config_data = xmlStrdup(BAD_CAST ""); } else { xmlDocDumpMemory(gds_startup, &config_data, NULL); } break; case NC_DATASTORE_CANDIDATE: if (!gds_cand) { config_data = xmlStrdup(BAD_CAST ""); } else { xmlDocDumpMemory(gds_cand, &config_data, NULL); } break; default: nc_verb_error("Invalid <get-config> source."); *error = nc_err_new(NC_ERR_BAD_ELEM); nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source"); } return (char *) config_data; }