This commit is contained in:
Olof hagsand 2016-03-07 20:55:55 +01:00
parent ca18b7f49e
commit 0a812696c2
47 changed files with 1818 additions and 1783 deletions

View file

@ -27,7 +27,7 @@ LIBS = @LIBS@
SHELL = /bin/sh
SUBDIRS = cli backend dbctrl netconf
SUBDIRS = cli backend dbctrl netconf xmldb
.PHONY: all clean depend install $(SUBDIRS)

View file

@ -54,7 +54,7 @@ INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/inclu
# Not accessible from plugin
APPSRC = backend_main.c backend_socket.c backend_client.c \
backend_lock.c backend_commit.c backend_plugin.c
backend_commit.c backend_plugin.c
APPOBJ = $(APPSRC:.c=.o)
APPL = clixon_backend

View file

@ -51,7 +51,6 @@
#include <clixon/clixon.h>
#include "backend_commit.h"
#include "backend_lock.h"
#include "backend_plugin.h"
#include "backend_client.h"
#include "backend_handle.h"
@ -163,7 +162,6 @@ backend_client_rm(clicon_handle h,
return backend_client_delete(h, ce); /* actually purge it */
}
/*! Internal message: Change entry set/delete in database xmldb variant
* @param[in] h Clicon handle
* @param[in] s Socket where request arrived, and where replies are sent
@ -183,15 +181,14 @@ from_client_change(clicon_handle h,
int retval = -1;
uint32_t len;
char *xk;
char *dbname;
char *db;
enum operation_type op;
char *str = NULL;
char *candidate_db;
char *val=NULL;
yang_spec *yspec;
int piddb;
if (clicon_msg_change_decode(msg,
&dbname,
&db,
&op,
&xk,
&val,
@ -201,25 +198,17 @@ from_client_change(clicon_handle h,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
/* candidate is locked by other client */
if (strcmp(dbname, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0,
"lock failed: locked by %d", db_islocked(h));
goto done;
if (strcmp(db, "candidate") == 0){
piddb = xmldb_islocked(h, db);
if (piddb && pid != piddb){
send_msg_err(s, OE_DB, 0,
"lock failed: locked by %d", piddb);
goto done;
}
}
/* Update database */
if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_XML, 0, "yang spec not found");
goto done;
}
if (xmldb_put_xkey(dbname, xk, val, yspec, op) < 0){
if (xmldb_put_xkey(h, db, xk, val, op) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
@ -233,8 +222,6 @@ from_client_change(clicon_handle h,
return retval;
}
/*! Internal message: Change entries as XML
* @param[in] h Clicon handle
* @param[in] s Socket where request arrived, and where replies are sent
@ -252,19 +239,16 @@ from_client_xmlput(clicon_handle h,
const char *label)
{
int retval = -1;
char *dbname;
char *db;
enum operation_type op;
cvec *cvv = NULL;
char *str = NULL;
char *xml = NULL;
yang_spec *ys;
char *candidate_db;
cxobj *xt;
int piddb;
if ((ys = clicon_dbspec_yang(h)) == NULL)
goto done;
if (clicon_msg_xmlput_decode(msg,
&dbname,
&db,
&op,
&xml,
label) < 0){
@ -272,24 +256,21 @@ from_client_xmlput(clicon_handle h,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
/* candidate is locked by other client */
if (strcmp(dbname, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0,
"lock failed: locked by %d", db_islocked(h));
goto done;
if (strcmp(db, "candidate") == 0){
piddb = xmldb_islocked(h, db);
if (piddb && pid != piddb){
send_msg_err(s, OE_DB, 0,
"lock failed: locked by %d", piddb);
goto done;
}
}
if (clicon_xml_parse_string(&xml, &xt) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if (xmldb_put(dbname, xt, ys, op) < 0){
if (xmldb_put(h, db, xt, op) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
@ -312,7 +293,7 @@ from_client_xmlput(clicon_handle h,
*/
int
config_snapshot(clicon_handle h,
char *dbname,
char *db,
char *dir)
{
int retval = -1;
@ -322,7 +303,6 @@ config_snapshot(clicon_handle h,
int i;
FILE *f = NULL;
cxobj *xn;
yang_spec *yspec = clicon_dbspec_yang(h);
if (stat(dir, &st) < 0){
clicon_err(OE_CFG, errno, "%s: stat(%s): %s\n",
@ -354,7 +334,7 @@ config_snapshot(clicon_handle h,
clicon_err(OE_CFG, errno, "Creating file %s", filename0);
return -1;
}
if (xmldb_get(dbname, "/", yspec, &xn) < 0)
if (xmldb_get(h, db, "/", 0, &xn, NULL, NULL) < 0)
goto done;
if (clicon_xml2file(f, xn, 0, 1) < 0)
goto done;
@ -389,7 +369,6 @@ from_client_save(clicon_handle h,
uint32_t snapshot;
FILE *f = NULL;
cxobj *xn = NULL;
yang_spec *yspec;
if (clicon_msg_save_decode(msg,
&db,
@ -400,6 +379,10 @@ from_client_save(clicon_handle h,
clicon_err_reason);
goto done;
}
if (strcmp(db, "running") != 0 && strcmp(db, "candidate") != 0){
clicon_err(OE_XML, 0, "Expected running or candidate, got %s", db);
goto done;
}
if (snapshot){
if ((archive_dir = clicon_archive_dir(h)) == NULL){
clicon_err(OE_PLUGIN, 0, "snapshot set and clicon_archive_dir not defined");
@ -417,8 +400,7 @@ from_client_save(clicon_handle h,
clicon_err(OE_CFG, errno, "Creating file %s", filename);
return -1;
}
yspec = clicon_dbspec_yang(h);
if (xmldb_get(db, "/", yspec, &xn) < 0)
if (xmldb_get(h, db, "/", 0, &xn, NULL, NULL) < 0)
goto done;
if (clicon_xml2file(f, xn, 0, 1) < 0)
goto done;
@ -453,40 +435,41 @@ from_client_load(clicon_handle h,
{
char *filename = NULL;
int retval = -1;
char *dbname = NULL;
char *db = NULL;
int replace = 0;
char *candidate_db;
int fd = -1;
cxobj *xt = NULL;
cxobj *xn;
yang_spec *yspec;
int piddb;
if (clicon_msg_load_decode(msg,
&replace,
&dbname,
&db,
&filename,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
if (strcmp(db, "running") != 0 && strcmp(db, "candidate") != 0){
clicon_err(OE_XML, 0, "Expected running or candidate, got %s", db);
goto done;
}
/* candidate is locked by other client */
if (strcmp(dbname, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h));
goto done;
if (strcmp(db, "candidate") == 0){
piddb = xmldb_islocked(h, db);
if (piddb && pid != piddb){
send_msg_err(s, OE_DB, 0,
"lock failed: locked by %d", piddb);
goto done;
}
}
if (replace){
if (unlink(dbname) < 0){
if (xmldb_delete(h, db) < 0){
send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
goto done;
}
if (xmldb_init(dbname) < 0)
if (xmldb_init(h, db) < 0)
goto done;
}
@ -501,9 +484,8 @@ from_client_load(clicon_handle h,
clicon_err_reason);
goto done;
}
yspec = clicon_dbspec_yang(h);
if ((xn = xml_child_i(xt, 0)) != NULL){
if (xmldb_put(dbname, xn, yspec, replace?OP_REPLACE:OP_MERGE) < 0){
if (xmldb_put(h, db, xn, replace?OP_REPLACE:OP_MERGE) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
@ -520,270 +502,6 @@ from_client_load(clicon_handle h,
return retval;
}
/*! Internal message: Initialize database
* @param[in] h Clicon handle
* @param[in] s Socket where request arrived, and where replies are sent
* @param[in] pid Unix process id
* @param[in] msg Message
* @param[in] label Memory chunk
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
*/
static int
from_client_initdb(clicon_handle h,
int s,
int pid,
struct clicon_msg *msg,
const char *label)
{
char *filename1;
int retval = -1;
char *candidate_db;
if (clicon_msg_initdb_decode(msg,
&filename1,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
/* candidate is locked by other client */
if (strcmp(filename1, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h));
goto done;
}
if (xmldb_init(filename1) < 0)
goto done;
/* Change mode if shared candidate. XXXX full rights for all is no good */
if (strcmp(filename1, candidate_db) == 0)
chmod(filename1, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (send_msg_ok(s) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Internal message: Remove file
* @param[in] h Clicon handle
* @param[in] s Socket where request arrived, and where replies are sent
* @param[in] pid Unix process id
* @param[in] msg Message
* @param[in] label Memory chunk
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
*/
static int
from_client_rm(clicon_handle h,
int s,
int pid,
struct clicon_msg *msg,
const char *label)
{
char *filename1;
int retval = -1;
char *candidate_db;
if (clicon_msg_rm_decode(msg,
&filename1,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
/* candidate is locked by other client */
if (strcmp(filename1, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h));
goto done;
}
if (unlink(filename1) < 0){
send_msg_err(s, OE_UNIX, 0, "rm %s %s", filename1, strerror(errno));
goto done;
}
if (send_msg_ok(s) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Internal message: Copy file from file1 to file2
* @param[in] h Clicon handle
* @param[in] s Socket where request arrived, and where replies are sent
* @param[in] pid Unix process id
* @param[in] msg Message
* @param[in] label Memory chunk
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
*/
static int
from_client_copy(clicon_handle h,
int s,
int pid,
struct clicon_msg *msg,
const char *label)
{
char *filename1;
char *filename2;
int retval = -1;
char *candidate_db;
if (clicon_msg_copy_decode(msg,
&filename1,
&filename2,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
/* candidate is locked by other client */
if (strcmp(filename2, candidate_db) == 0 &&
db_islocked(h) &&
pid != db_islocked(h)){
send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h));
goto done;
}
if (file_cp(filename1, filename2) < 0){
send_msg_err(s, OE_UNIX, errno, "copy %s to %s", filename1, filename2);
goto done;
}
/* Change mode if shared candidate. XXXX full rights for all is no good */
if (strcmp(filename2, candidate_db) == 0)
chmod(filename2, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (send_msg_ok(s) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Internal message: Lock database
* @param[in] h Clicon handle
* @param[in] s Client socket where request arrived, and where replies are sent
* @param[in] pid Client unix process id
* @param[in] msg Message
* @param[in] label Memory chunk
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
*/
static int
from_client_lock(clicon_handle h,
int s,
int pid,
struct clicon_msg *msg,
const char *label)
{
char *db;
int retval = -1;
char *candidate_db;
if (clicon_msg_lock_decode(msg,
&db,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
if (strcmp(db, candidate_db)){
send_msg_err(s, OE_DB, 0, "can not lock %s, only %s",
db, candidate_db);
goto done;
}
if (db_islocked(h)){
if (pid == db_islocked(h))
;
else{
send_msg_err(s, OE_DB, 0, "lock failed: locked by %d", db_islocked(h));
goto done;
}
}
else
db_lock(h, pid);
if (send_msg_ok(s) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Internal message: Unlock database
* @param[in] h Clicon handle
* @param[in] s Client socket where request arrived, and where replies are sent
* @param[in] pid Client unix process id
* @param[in] msg Message
* @param[in] label Memory chunk
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
*/
static int
from_client_unlock(clicon_handle h,
int s,
int pid,
struct clicon_msg *msg,
const char *label)
{
char *db;
int retval = -1;
char *candidate_db;
if (clicon_msg_unlock_decode(msg,
&db,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
send_msg_err(s, 0, 0, "candidate db not set");
goto done;
}
if (strcmp(db, candidate_db)){
send_msg_err(s, OE_DB, 0, "can not unlock %s, only %s",
db, clicon_candidate_db(h));
goto done;
}
if (db_islocked(h)){
if (pid == db_islocked(h))
db_unlock(h);
else{
send_msg_err(s, OE_DB, 0, "unlock failed: locked by %d", db_islocked(h));
goto done;
}
}
if (send_msg_ok(s) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Internal message: Kill session (Kill the process)
* @param[in] h Clicon handle
* @param[in] s Client socket where request arrived, and where replies are sent
@ -798,9 +516,10 @@ from_client_kill(clicon_handle h,
struct clicon_msg *msg,
const char *label)
{
uint32_t pid; /* other pid */
int retval = -1;
int retval = -1;
uint32_t pid; /* other pid */
struct client_entry *ce;
char *db = "running"; /* XXX */
if (clicon_msg_kill_decode(msg,
&pid,
@ -823,8 +542,8 @@ from_client_kill(clicon_handle h,
}
if (1 || (kill (pid, 0) != 0 && errno == ESRCH)){ /* Nothing there */
/* clear from locks */
if (db_islocked(h) == pid)
db_unlock(h);
if (xmldb_islocked(h, db) == pid)
xmldb_unlock(h, db, pid);
}
else{ /* failed to kill client */
send_msg_err(s, OE_DB, 0, "failed to kill %d", pid);
@ -1017,26 +736,6 @@ from_client(int s, void* arg)
if (from_client_load(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_RM:
if (from_client_rm(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_INITDB:
if (from_client_initdb(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_COPY:
if (from_client_copy(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_LOCK:
if (from_client_lock(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_UNLOCK:
if (from_client_unlock(h, ce->ce_s, ce->ce_pid, msg, __FUNCTION__) < 0)
goto done;
break;
case CLICON_MSG_KILL:
if (from_client_kill(h, ce->ce_s, msg, __FUNCTION__) < 0)
goto done;

View file

@ -117,18 +117,14 @@ generic_validate(yang_spec *yspec,
* fails, we just ignore the errors and proceed. Maybe we should
* do something more drastic?
* @param[in] h Clicon handle
* @param[in] running The current database. The original backend state
* @param[in] candidate: The candidate database. The wanted backend state
*/
int
candidate_commit(clicon_handle h,
char *candidate,
char *running)
char *candidate)
{
int retval = -1;
int i;
cxobj *xn;
struct stat sb;
void *firsterr = NULL;
yang_spec *yspec;
transaction_data_t *td = NULL;
@ -137,24 +133,15 @@ candidate_commit(clicon_handle h,
clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done;
}
/* Sanity checks that databases exists. */
if (stat(running, &sb) < 0){
clicon_err(OE_DB, errno, "%s", running);
goto done;
}
if (stat(candidate, &sb) < 0){
clicon_err(OE_DB, errno, "%s", candidate);
goto done;
}
/* 1. Start transaction */
if ((td = transaction_new()) == NULL)
goto done;
/* 2. Parse xml trees */
if (xmldb_get(running, "/", yspec, &td->td_src) < 0)
if (xmldb_get(h, "running", "/", 0, &td->td_src, NULL, NULL) < 0)
goto done;
if (xmldb_get(candidate, "/", yspec, &td->td_target) < 0)
if (xmldb_get(h, candidate, "/", 0, &td->td_target, NULL, NULL) < 0)
goto done;
/* 3. Compute differences */
@ -212,18 +199,15 @@ candidate_commit(clicon_handle h,
goto done;
/* 8. Success: Copy candidate to running */
if (file_cp(candidate, running) < 0){
clicon_err(OE_UNIX, errno, "file_cp(candidate; running)");
if (xmldb_copy(h, candidate, "running") < 0)
goto done;
}
/* 9. Call plugin transaction end callbacks */
plugin_transaction_end(h, td);
/* 8. Copy running back to running in case end functions updated running */
if (file_cp(running, candidate) < 0){
/* 8. Copy running back to candidate in case end functions updated running */
if (xmldb_copy(h, "running", candidate) < 0){
/* ignore errors or signal major setback ? */
clicon_err(OE_UNIX, errno, "file_cp(running, candidate)");
clicon_log(LOG_NOTICE, "Error in rollback, trying to continue");
goto done;
}
@ -243,16 +227,13 @@ candidate_commit(clicon_handle h,
/*! Do a diff between candidate and running, then start a validate transaction
*
* @param[in] h Clicon handle
* @param[in] running The current database. The original backend state
* @param[in] candidate: The candidate database. The wanted backend state
*/
int
candidate_validate(clicon_handle h,
char *candidate,
char *running)
{
char *candidate)
{
int retval = -1;
struct stat sb;
yang_spec *yspec;
transaction_data_t *td = NULL;
int i;
@ -262,24 +243,15 @@ candidate_validate(clicon_handle h,
clicon_err(OE_FATAL, 0, "No DB_SPEC");
goto done;
}
/* Sanity checks that databases exists. */
if (stat(running, &sb) < 0){
clicon_err(OE_DB, errno, "%s", running);
goto done;
}
if (stat(candidate, &sb) < 0){
clicon_err(OE_DB, errno, "%s", candidate);
goto done;
}
/* 1. Start transaction */
if ((td = transaction_new()) == NULL)
goto done;
/* 2. Parse xml trees */
if (xmldb_get(running, "/", yspec, &td->td_src) < 0)
if (xmldb_get(h, "running", "/", 0, &td->td_src, NULL, NULL) < 0)
goto done;
if (xmldb_get(candidate, "/", yspec, &td->td_target) < 0)
if (xmldb_get(h, "candidate", "/", 0, &td->td_target, NULL, NULL) < 0)
goto done;
/* 3. Compute differences */
@ -346,25 +318,36 @@ candidate_validate(clicon_handle h,
* the commit has succeeded but an error message is returned.
*/
int
from_client_commit(clicon_handle h,
int s,
from_client_commit(clicon_handle h,
int s,
struct clicon_msg *msg,
const char *label)
const char *label)
{
int retval = -1;
char *candidate;
char *running;
uint32_t snapshot;
uint32_t startup;
char *snapshot_0;
char *archive_dir;
char *startup_config;
if (clicon_msg_commit_decode(msg, &candidate, &running,
&snapshot, &startup, label) < 0)
if (clicon_msg_commit_decode(msg,
&candidate,
&running,
&snapshot,
&startup,
label) < 0)
goto err;
if (candidate_commit(h, candidate, running) < 0){
if (strcmp(candidate, "candidate") && strcmp(candidate, "tmp")){
clicon_err(OE_PLUGIN, 0, "candidate is not \"candidate\" or tmp");
goto err;
}
if (strcmp(running, "running")){
clicon_err(OE_PLUGIN, 0, "running db is not \"running\"");
goto err;
}
if (candidate_commit(h, "candidate") < 0){
clicon_debug(1, "Commit %s failed", candidate);
retval = 0; /* We ignore errors from commit, but maybe
we should fail on fatal errors? */
@ -389,8 +372,7 @@ from_client_commit(clicon_handle h,
clicon_err(OE_PLUGIN, 0, "startup set but startup_config not defined");
goto err;
}
snapshot_0 = chunk_sprintf(__FUNCTION__, "%s/0", archive_dir);
if (file_cp(snapshot_0, startup_config) < 0){
if (clicon_file_copy("snapshot", "startup") < 0){
clicon_err(OE_PROTO, errno, "%s: Error when creating startup",
__FUNCTION__);
goto err;
@ -412,32 +394,31 @@ from_client_commit(clicon_handle h,
/*
* Call backend plugin
/*! Handle an incoming validate message from a client.
*/
int
from_client_validate(clicon_handle h,
int s,
from_client_validate(clicon_handle h,
int s,
struct clicon_msg *msg,
const char *label)
const char *label)
{
char *dbname;
char *running_db;
int retval = -1;
int retval = -1;
char *candidate;
if (clicon_msg_validate_decode(msg, &dbname, label) < 0){
if (clicon_msg_validate_decode(msg,
&candidate,
label) < 0){
send_msg_err(s, clicon_errno, clicon_suberrno,
clicon_err_reason);
goto err;
}
clicon_debug(1, "Validate %s", dbname);
if ((running_db = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
goto err;
if (strcmp(candidate, "candidate") != 0 && strcmp(candidate, "tmp") != 0){
clicon_err(OE_PLUGIN, 0, "candidate is not \"candidate\" or tmp");
goto err;
}
if (candidate_validate(h, dbname, running_db) < 0){
clicon_debug(1, "Validate %s failed", dbname);
clicon_debug(1, "Validate %s", candidate);
if (candidate_validate(h, candidate) < 0){
clicon_debug(1, "Validate %s failed", candidate);
retval = 0; /* We ignore errors from commit, but maybe
we should fail on fatal errors? */
goto err;

View file

@ -29,6 +29,6 @@
*/
int from_client_validate(clicon_handle h, int s, struct clicon_msg *msg, const char *label);
int from_client_commit(clicon_handle h, int s, struct clicon_msg *msg, const char *label);
int candidate_commit(clicon_handle h, char *candidate, char *running);
int candidate_commit(clicon_handle h, char *candidate);
#endif /* _BACKEND_COMMIT_H_ */

View file

@ -1,95 +0,0 @@
/*
*
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
CLIXON is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
CLIXON is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CLIXON; see the file LICENSE. If not, see
<http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <netinet/in.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include <clixon/clixon.h>
#include "backend_lock.h"
/*
* Easy way out: store an integer for candidate db which contains
* the session-id of the client holding the lock.
* more general: any database
* we dont make any sanity check on who is locking.
*/
static int _db_locked = 0;
/*
* db_lock
*/
int
db_lock(clicon_handle h, int id)
{
_db_locked = id;
clicon_debug(1, "%s: lock db by %u", __FUNCTION__, id);
return 0;
}
/*
* db_unlock
*/
int
db_unlock(clicon_handle h)
{
if (!_db_locked )
return 0;
_db_locked = 0;
return 0;
}
/*
* db_islocked
* returns id of locker
*/
int
db_islocked(clicon_handle h)
{
return _db_locked;
}

View file

@ -1,37 +0,0 @@
/*
*
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
CLIXON is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
CLIXON is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CLIXON; see the file LICENSE. If not, see
<http://www.gnu.org/licenses/>.
*
* Database logical lock functions.
* Only one lock (candidate_db)
* Not persistent (needs another db)
*/
#ifndef _BACKEND_LOCK_H_
#define _BACKEND_LOCK_H_
/*
* Prototypes
*/
int db_lock(clicon_handle h, int id);
int db_unlock(clicon_handle h);
int db_islocked(clicon_handle h);
#endif /* _BACKEND_LOCK_H_ */

View file

@ -59,9 +59,9 @@
#include "backend_handle.h"
/* Command line options to be passed to getopt(3) */
#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc::rg:pt"
#define BACKEND_OPTS "hD:f:d:Fzu:P:1IRCc::rg:ptx:"
/* Cannot use h after this */
/*! Terminate. Cannot use h after this */
static int
config_terminate(clicon_handle h)
{
@ -85,10 +85,8 @@ config_terminate(clicon_handle h)
return 0;
}
/*
config_sig_term
Unlink pidfile and quit
*/
/*! Unlink pidfile and quit
*/
static void
config_sig_term(int arg)
{
@ -130,7 +128,8 @@ usage(char *argv0, clicon_handle h)
" -r\t\tReload running database\n"
" -p \t\tPrint database yang specification\n"
" -t \t\tPrint alternate spec translation (eg if YANG print KEY, if KEY print YANG)\n"
" -g <group>\tClient membership required to this group (default: %s)\n",
" -g <group>\tClient membership required to this group (default: %s)\n"
" -x <status>\tSet CLICON_XMLDB_RPC to 0 or 1.\n",
argv0,
plgdir ? plgdir : "none",
confsock ? confsock : "none",
@ -138,19 +137,16 @@ usage(char *argv0, clicon_handle h)
startup ? startup : "none",
group ? group : "none"
);
exit(0);
exit(-1);
}
static int
rundb_init(clicon_handle h, char *running_db)
rundb_init(clicon_handle h)
{
if (unlink(running_db) != 0 && errno != ENOENT) {
clicon_err(OE_UNIX, errno, "unlink");
if (xmldb_delete(h, "running") != 0 && errno != ENOENT)
return -1;
}
if (xmldb_init(running_db) < 0)
if (xmldb_init(h, "running") < 0)
return -1;
return 0;
}
@ -164,19 +160,16 @@ rundb_init(clicon_handle h, char *running_db)
*/
static int
rundb_main(clicon_handle h,
char *app_config_file,
char *running_db)
char *app_config_file)
{
char *tmp = NULL;
int retval = -1;
int fd = -1;
yang_spec *yspec;
cxobj *xt = NULL;
cxobj *xn;
if ((tmp = clicon_tmpfile(__FUNCTION__)) == NULL)
if (xmldb_init(h, "tmp") < 0)
goto done;
if (file_cp(running_db, tmp) < 0){
if (xmldb_copy(h, "running", "tmp") < 0){
clicon_err(OE_UNIX, errno, "file copy");
goto done;
}
@ -186,16 +179,15 @@ rundb_main(clicon_handle h,
}
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
yspec = clicon_dbspec_yang(h);
if ((xn = xml_child_i(xt, 0)) != NULL)
if (xmldb_put(tmp, xn, yspec, OP_MERGE) < 0)
if (xmldb_put(h, "tmp", xn, OP_MERGE) < 0)
goto done;
if (candidate_commit(h, tmp, running_db) < 0)
if (candidate_commit(h, "tmp") < 0)
goto done;
if (xmldb_delete(h, "tmp") < 0)
goto done;
retval = 0;
done:
if (tmp)
unlink(tmp);
if (xt)
xml_free(xt);
if (fd != -1)
@ -204,31 +196,24 @@ done:
return retval;
}
static int
candb_reset(clicon_handle h, char *running_db)
candb_reset(clicon_handle h)
{
int retval = -1;
char *tmp = NULL;
if ((tmp = clicon_tmpfile(__FUNCTION__)) == NULL)
goto done;
if (file_cp(running_db, tmp) < 0){
if (xmldb_copy(h, "running", "tmp") < 0){
clicon_err(OE_UNIX, errno, "file copy");
goto done;
}
/* Request plugins to reset system state, eg initiate running from system
* -R
*/
if (plugin_reset_state(h, tmp) < 0)
if (plugin_reset_state(h, "tmp") < 0)
goto done;
if (candidate_commit(h, tmp, running_db) < 0)
if (candidate_commit(h, "tmp") < 0)
goto done;
retval = 0;
done:
if (tmp)
unlink(tmp);
unchunk_group(__FUNCTION__);
return retval;
}
@ -299,8 +284,6 @@ main(int argc, char **argv)
int foreground;
int once;
int init_rundb;
char *running_db;
char *candidate_db;
int reload_running;
int reset_state_running;
int reset_state_candidate;
@ -431,6 +414,14 @@ main(int argc, char **argv)
case 't' : /* Print alternative dbspec format (eg if YANG, print KEY) */
printalt++;
break;
case 'x' : /* set xmldb rpc on */
{
int i;
if (sscanf(optarg, "%d", &i) != 1)
usage(argv[0], h);
clicon_option_int_set(h, "CLICON_XMLDB_RPC", i);
}
break;
default:
usage(argv[0], h);
break;
@ -462,7 +453,7 @@ main(int argc, char **argv)
unlink(pidfile);
if (sockfamily==AF_UNIX && lstat(sock, &st) == 0)
unlink(sock);
exit(0);
exit(0); /* OK */
}
else
if (pid){
@ -500,31 +491,21 @@ main(int argc, char **argv)
if (yang_spec_main(h, stdout, printspec) < 0)
goto done;
if ((running_db = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
/* If running exists and reload_running set, make a copy to candidate */
if (reload_running){
if (stat(running_db, &st) && errno == ENOENT){
if (xmldb_exists(h, "running") != 1){
clicon_log(LOG_NOTICE, "%s: -r (reload running) option given but no running_db found, proceeding without", __PROGRAM__);
reload_running = 0; /* void it, so we dont commit candidate below */
}
else
if (file_cp(running_db, candidate_db) < 0){
clicon_err(OE_UNIX, errno, "FATAL: file_cp");
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
}
/* Init running db
* -I
* -I or if it isnt there
*/
if (init_rundb || (stat(running_db, &st) && errno == ENOENT))
if (rundb_init(h, running_db) < 0)
if (init_rundb || xmldb_exists(h, "running") != 1)
if (rundb_init(h) < 0)
goto done;
/* Initialize plugins
@ -533,12 +514,12 @@ main(int argc, char **argv)
goto done;
if (reset_state_candidate){
if (candb_reset(h, running_db) < 0)
if (candb_reset(h) < 0)
goto done;
}
else
if (reset_state_running){
if (plugin_reset_state(h, running_db) < 0)
if (plugin_reset_state(h, "running") < 0)
goto done;
}
/* Call plugin_start */
@ -549,7 +530,7 @@ main(int argc, char **argv)
*(argv-1) = tmp;
if (reload_running){
if (candidate_commit(h, candidate_db, running_db) < 0)
if (candidate_commit(h, "candidate") < 0)
goto done;
}
@ -558,17 +539,16 @@ main(int argc, char **argv)
-r replace running (obsolete)
*/
if (app_config_file)
if (rundb_main(h, app_config_file, running_db) < 0)
if (rundb_main(h, app_config_file) < 0)
goto done;
/* Initiate the shared candidate. Maybe we should not do this? */
if (file_cp(running_db, candidate_db) < 0){
clicon_err(OE_UNIX, errno, "FATAL: file_cp");
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
#ifdef OBSOLETE
/* XXX Hack for now. Change mode so that we all can write. Security issue*/
chmod(candidate_db, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
#endif
if (once)
goto done;
@ -579,7 +559,7 @@ main(int argc, char **argv)
clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, CLICON_LOG_SYSLOG);
if (daemon(0, 0) < 0){
fprintf(stderr, "config: daemon");
exit(0);
exit(-1);
}
}
/* Write pid-file */

View file

@ -69,57 +69,17 @@ static int xml2csv(FILE *f, cxobj *x, cvec *cvv);
* shared - all users share a common candidate db
*/
int
init_candidate_db(clicon_handle h, enum candidate_db_type type)
init_candidate_db(clicon_handle h)
{
int retval = -1;
struct stat sb;
char *running_db;
char *candidate_db;
int retval = -1;
if ((running_db = clicon_running_db(h)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: RUNNING_CANDIDATE_DB option not set", __FUNCTION__);
if (xmldb_exists(h, "running") != 1){
clicon_err(OE_FATAL, 0, "Running db does not exist");
goto err;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: CLICON_CANDIDATE_DB option not set", __FUNCTION__);
goto err;
}
cli_set_candidate_type(h, type);
switch(type){
case CANDIDATE_DB_NONE:
break;
case CANDIDATE_DB_PRIVATE:
if (lstat(candidate_db, &sb) < 0){
if (file_cp(running_db, candidate_db) < 0){
clicon_err(OE_UNIX, errno, "Error when copying %s to %s",
running_db, candidate_db);
unlink(candidate_db);
goto err;
}
}
break;
case CANDIDATE_DB_SHARED:
if (lstat(running_db, &sb) < 0){
clicon_err(OE_FATAL, 0, "Running db (%s) does not exist",
running_db);
if (xmldb_exists(h, "candidate") != 1)
if (xmldb_copy(h, "running", "candidate") < 0)
goto err;
}
if (lstat(candidate_db, &sb) < 0){
if (cli_send2backend(h)) {
clicon_rpc_copy(h, running_db, candidate_db);
}
else
if (file_cp(running_db, candidate_db) < 0){
clicon_err(OE_UNIX, errno, "Error when copying %s to %s",
running_db, candidate_db);
goto err;
}
}
break;
case CANDIDATE_DB_CURRENT:
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", running_db);
break;
}
retval = 0;
err:
return retval;
@ -132,18 +92,6 @@ init_candidate_db(clicon_handle h, enum candidate_db_type type)
int
exit_candidate_db(clicon_handle h)
{
// struct stat sb;
switch(cli_candidate_type(h)){
case CANDIDATE_DB_PRIVATE:
#if 0 /* XXX: maybe we should remove it, but I want several cli:s to edit it */
if (lstat(clicon_candidate_db(h), &sb) == 0)
unlink(clicon_candidate_db(h));
#endif
break;
default:
break;
}
return 0;
}
@ -165,10 +113,8 @@ cli_debug(clicon_handle h, cvec *vars, cg_var *arg)
/* cli */
clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */
/* config daemon */
if (cli_send2backend(h)) {
if (clicon_rpc_debug(h, level) < 0)
goto done;
}
if (clicon_rpc_debug(h, level) < 0)
goto done;
done:
return 0;
}
@ -351,29 +297,20 @@ cli_quit(clicon_handle h, cvec *vars, cg_var *arg)
return 0;
}
/*
* Generic commit callback
* if arg is 1, then snapshot and copy to startup config
/*! Generic commit callback
* @param[in] arg If 1, then snapshot and copy to startup config
*/
int
cli_commit(clicon_handle h, cvec *vars, cg_var *arg)
cli_commit(clicon_handle h,
cvec *vars,
cg_var *arg)
{
int retval = -1;
int snapshot = arg?cv_int32_get(arg):0;
char *candidate;
char *running;
if ((running = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
goto done;
}
if ((candidate = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
if ((retval = clicon_rpc_commit(h,
running,
candidate,
"running",
"candidate",
snapshot, /* snapshot */
snapshot)) < 0){ /* startup */
cli_output(stderr, "Commit failed. Edit and try again or discard changes\n");
@ -390,17 +327,10 @@ cli_commit(clicon_handle h, cvec *vars, cg_var *arg)
int
cli_validate(clicon_handle h, cvec *vars, cg_var *arg)
{
char *candidate_db;
int retval = -1;
if ((candidate_db = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
return -1;
}
if (cli_send2backend(h)) {
if ((retval = clicon_rpc_validate(h, candidate_db)) < 0)
cli_output(stderr, "Validate failed. Edit and try again or discard changes\n");
}
if ((retval = clicon_rpc_validate(h, "candidate")) < 0)
cli_output(stderr, "Validate failed. Edit and try again or discard changes\n");
return retval;
}
@ -447,7 +377,6 @@ expand_dbvar_dbxml(void *h,
char ***commands,
char ***helptexts)
{
char *dbname;
int nvec;
char **vec = NULL;
int retval = -1;
@ -457,10 +386,11 @@ expand_dbvar_dbxml(void *h,
cxobj *xt = NULL;
char *xk = NULL;
cxobj **xvec = NULL;
size_t xlen = 0;
cxobj *x;
char *bodystr;
int i;
int i0;
size_t xlen;
yang_spec *yspec;
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
@ -472,37 +402,34 @@ expand_dbvar_dbxml(void *h,
goto done;
}
dbstr = vec[0];
if (strcmp(dbstr, "running") == 0)
dbname = clicon_running_db(h);
else
if (strcmp(dbstr, "candidate") == 0)
dbname = clicon_candidate_db(h);
else{
if (strcmp(dbstr, "running") != 0 &&
strcmp(dbstr, "candidate") != 0){
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
goto done;
}
if (dbname == NULL){
clicon_err(OE_FATAL, 0, "db not set");
goto done;
}
xkfmt = vec[1];
/* xkfmt = /interface/%s/address/%s
--> ^/interface/eth0/address/.*$
--> /interface/[name=eth0]/address
*/
if (xmlkeyfmt2xpath(xkfmt, cvv, &xk) < 0)
goto done;
yspec = clicon_dbspec_yang(h);
if (xmldb_get_vec(dbname, xk, yspec, &xt, &xvec, &xlen) < 0)
goto done;
if (xmldb_get(h, dbstr, xk, 1, &xt, &xvec, &xlen) < 0)
goto done;
i0 = *nr;
*nr += xlen;
if ((*commands = realloc(*commands, sizeof(char *) * (*nr))) == NULL) {
clicon_err(OE_UNDEF, errno, "realloc: %s", strerror (errno));
clicon_err(OE_UNIX, errno, "realloc: %s", strerror (errno));
goto done;
}
for (i = 0; i < xlen; i++)
(*commands)[i0+i] = strdup(xml_body(xvec[i]));
for (i = 0; i < xlen; i++) {
x = xvec[i];
if ((bodystr = xml_body(x)) == NULL){
clicon_err(OE_CFG, 0, "No xml body");
goto done;
}
(*commands)[i0+i] = strdup(bodystr);
}
retval = 0;
done:
unchunk_group(__FUNCTION__);
@ -634,14 +561,16 @@ expand_dir(char *dir, int *nr, char ***commands, mode_t flags, int detail)
/*! Compare two dbs using XML. Write to file and run diff
*/
static int
compare_xmls(cxobj *xc1, cxobj *xc2, int astext)
compare_xmls(cxobj *xc1,
cxobj *xc2,
int astext)
{
int fd;
FILE *f;
char filename1[MAXPATHLEN];
char filename2[MAXPATHLEN];
char cmd[MAXPATHLEN];
int retval = -1;
int fd;
FILE *f;
char filename1[MAXPATHLEN];
char filename2[MAXPATHLEN];
char cmd[MAXPATHLEN];
int retval = -1;
cxobj *xc;
snprintf(filename1, sizeof(filename1), "/tmp/cliconXXXXXX");
@ -701,20 +630,10 @@ compare_dbs(clicon_handle h, cvec *cvv, cg_var *arg)
cxobj *xc1 = NULL; /* running xml */
cxobj *xc2 = NULL; /* candidate xml */
int retval = -1;
char *running;
char *candidate;
if ((running = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
if (xmldb_get(h, "running", "/", 0, &xc1, NULL, NULL) < 0)
goto done;
}
if ((candidate = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
if (xmldb_get(running, "/", clicon_dbspec_yang(h), &xc1) < 0)
goto done;
if (xmldb_get(candidate, "/", clicon_dbspec_yang(h), &xc2) < 0)
if (xmldb_get(h, "candidate", "/", 0, &xc2, NULL, NULL) < 0)
goto done;
if (compare_xmls(xc1, xc2, arg?cv_int32_get(arg):0) < 0) /* astext? */
goto done;
@ -752,13 +671,10 @@ cli_dbxml(clicon_handle h,
{
int retval = -1;
char *str = NULL;
char *candidate;
char *running;
char *xkfmt; /* xml key format */
char *xk = NULL; /* xml key */
cg_var *cval;
char *val = NULL;
yang_spec *yspec;
/*
* clicon_rpc_xmlput(h, db, MERGE,"<interfaces><interface><name>eth0</name><type>hej</type></interface><interfaces>");
@ -772,14 +688,6 @@ cli_dbxml(clicon_handle h,
* Where is arg computed? In eg yang2cli_leaf, otherwise in yang_parse,..
* Create string using cbuf and save that.
*/
if ((candidate = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
return -1;
}
if ((running = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
return -1;
}
xkfmt = cv_string_get(arg);
if (xmlkeyfmt2key(xkfmt, cvv, &xk) < 0)
goto done;
@ -788,20 +696,11 @@ cli_dbxml(clicon_handle h,
clicon_err(OE_UNIX, errno, "cv2str_dup");
goto done;
}
if (cli_send2backend(h)) {
if (clicon_rpc_change(h, candidate, op, xk, val) < 0)
if (clicon_rpc_change(h, "candidate", op, xk, val) < 0)
goto done;
if (clicon_autocommit(h)) {
if (clicon_rpc_commit(h, "running", "candidate", 0, 0) < 0)
goto done;
if (clicon_autocommit(h)) {
if (clicon_rpc_commit(h, running, candidate, 0, 0) < 0)
goto done;
}
}
else{
yspec = clicon_dbspec_yang(h);
if (xmldb_put_xkey(candidate, xk, val, yspec, op) < 0)
goto done;
if (clicon_autocommit(h))
clicon_log(LOG_WARNING, "Cant combine no backend and autocommit");
}
retval = 0;
done:
@ -863,7 +762,9 @@ cli_del(clicon_handle h, cvec *cvv, cg_var *arg)
* @see save_config_file
*/
int
load_config_file(clicon_handle h, cvec *cvv, cg_var *arg)
load_config_file(clicon_handle h,
cvec *cvv,
cg_var *arg)
{
int ret = -1;
struct stat st;
@ -871,7 +772,6 @@ load_config_file(clicon_handle h, cvec *cvv, cg_var *arg)
char **vecp;
char *filename;
int replace;
char *dbname;
char *str;
cg_var *cv;
int nvec;
@ -882,7 +782,6 @@ load_config_file(clicon_handle h, cvec *cvv, cg_var *arg)
cxobj *xn;
cxobj *x;
cbuf *cbxml;
yang_spec *yspec;
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
@ -916,57 +815,30 @@ load_config_file(clicon_handle h, cvec *cvv, cg_var *arg)
goto done;
}
filename = vecp[0];
if ((dbname = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
if (stat(filename, &st) < 0){
clicon_err(OE_UNIX, 0, "load_config: stat(%s): %s\n",
filename, strerror(errno));
goto done;
}
if (cli_send2backend(h)) {
/* Open and parse local file into xml */
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
goto done;
}
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
if ((xn = xml_child_i(xt, 0)) != NULL){
if ((cbxml = cbuf_new()) == NULL)
goto done;
x = NULL;
while ((x = xml_child_each(xn, x, -1)) != NULL)
if (clicon_xml2cbuf(cbxml, x, 0, 0) < 0)
goto done;
if (clicon_rpc_xmlput(h, dbname,
replace?OP_REPLACE:OP_MERGE,
cbuf_get(cbxml)) < 0)
goto done;
cbuf_free(cbxml);
}
/* Open and parse local file into xml */
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
goto done;
}
else{
if (replace){
if (unlink(dbname) < 0){
clicon_err(OE_UNIX, 0, "rm %s %s", filename, strerror(errno));
goto done;
}
if (xmldb_init(dbname) < 0)
goto done;
}
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
if ((xn = xml_child_i(xt, 0)) != NULL){
if ((cbxml = cbuf_new()) == NULL)
goto done;
}
if (clicon_xml_parse_file(fd, &xt, "</clicon>") < 0)
goto done;
yspec = clicon_dbspec_yang(h);
if ((xn = xml_child_i(xt, 0)) != NULL){
if (xmldb_put(dbname, xn, yspec, replace?OP_REPLACE:OP_MERGE) < 0)
x = NULL;
while ((x = xml_child_each(xn, x, -1)) != NULL)
if (clicon_xml2cbuf(cbxml, x, 0, 0) < 0)
goto done;
}
if (clicon_rpc_xmlput(h, "candidate",
replace?OP_REPLACE:OP_MERGE,
cbuf_get(cbxml)) < 0)
goto done;
cbuf_free(cbxml);
}
ret = 0;
done:
@ -1001,7 +873,6 @@ save_config_file(clicon_handle h,
char **vec;
char **vecp;
char *filename;
char *dbname;
cg_var *cv;
int nvec;
char *str;
@ -1009,7 +880,6 @@ save_config_file(clicon_handle h,
char *varstr;
cxobj *xt = NULL;
FILE *f = NULL;
yang_spec *yspec;
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
@ -1025,20 +895,10 @@ save_config_file(clicon_handle h,
}
dbstr = vec[0];
varstr = vec[1];
if (strcmp(dbstr, "running") == 0)
dbname = clicon_running_db(h);
else
if (strcmp(dbstr, "candidate") == 0)
dbname = clicon_candidate_db(h);
else{
if (strcmp(dbstr, "running") != 0 && strcmp(dbstr, "candidate") != 0) {
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
goto done;
}
if (dbname == NULL){
clicon_err(OE_FATAL, 0, "dbname not set");
goto done;
}
if ((cv = cvec_find_var(cvv, varstr)) == NULL){
clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr);
goto done;
@ -1048,8 +908,7 @@ save_config_file(clicon_handle h,
goto done;
}
filename = vecp[0];
yspec = clicon_dbspec_yang(h);
if (xmldb_get(dbname, "/", yspec, &xt) < 0)
if (xmldb_get(h, dbstr, "/", 0, &xt, NULL, NULL) < 0)
goto done;
if ((f = fopen(filename, "wb")) == NULL){
clicon_err(OE_CFG, errno, "Creating file %s", filename);
@ -1074,7 +933,6 @@ save_config_file(clicon_handle h,
int
delete_all(clicon_handle h, cvec *cvv, cg_var *arg)
{
char *dbname;
char *dbstr;
int retval = -1;
@ -1082,31 +940,14 @@ delete_all(clicon_handle h, cvec *cvv, cg_var *arg)
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
goto done;
}
if (strcmp(dbstr, "running") == 0)
dbname = clicon_running_db(h);
else
if (strcmp(dbstr, "candidate") == 0)
dbname = clicon_candidate_db(h);
else{
if (strcmp(dbstr, "running") != 0 && strcmp(dbstr, "candidate") != 0){
clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);
goto done;
}
if (dbname == NULL){
clicon_err(OE_FATAL, 0, "dbname not set");
if (xmldb_delete(h, dbstr) < 0)
goto done;
if (xmldb_init(h, dbstr) < 0)
goto done;
}
if (cli_send2backend(h)) {
clicon_rpc_rm(h, dbname);
clicon_rpc_initdb(h, dbname);
}
else{
if (unlink(dbname) < 0){
clicon_err(OE_FATAL, errno, "unlink(%s)", dbname);
goto done;
}
if (xmldb_init(dbname) < 0)
goto done;
}
retval = 0;
done:
return retval;
@ -1118,22 +959,7 @@ delete_all(clicon_handle h, cvec *cvv, cg_var *arg)
int
discard_changes(clicon_handle h, cvec *cvv, cg_var *arg)
{
char *running_db;
char *candidate_db;
int retval = -1;
if ((candidate_db = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
if ((running_db = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
goto done;
}
clicon_rpc_copy(h, running_db, candidate_db);
retval = 0;
done:
return retval;
return xmldb_copy(h, "running", "candidate");
}
/*! Generic function for showing configurations.
@ -1157,12 +983,11 @@ show_conf_xmldb_as(clicon_handle h,
cxobj **xt) /* top xml */
{
int retval = -1;
char *dbname;
char *db;
char **vec = NULL;
int nvec;
char *str;
char *xpath;
yang_spec *yspec;
if (arg == NULL || (str = cv_string_get(arg)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: requires string argument", __FUNCTION__);
@ -1177,22 +1002,13 @@ show_conf_xmldb_as(clicon_handle h,
goto done;
}
/* Dont get attr here, take it from arg instead */
if (strcmp(vec[0], "running") == 0) /* XXX: hardcoded */
dbname = clicon_running_db(h);
else
if (strcmp(vec[0], "candidate") == 0) /* XXX: hardcoded */
dbname = clicon_candidate_db(h);
else{
clicon_err(OE_PLUGIN, 0, "No such db name: %s", vec[0]);
goto done;
}
if (dbname == NULL){
clicon_err(OE_FATAL, 0, "dbname not set");
db = vec[0];
if (strcmp(db, "running") != 0 && strcmp(db, "candidate") != 0) {
clicon_err(OE_PLUGIN, 0, "No such db name: %s", db);
goto done;
}
xpath = vec[1];
yspec = clicon_dbspec_yang(h);
if (xmldb_get(dbname, xpath, yspec, xt) < 0)
if (xmldb_get(h, db, xpath, 0, xt, NULL, NULL) < 0)
goto done;
retval = 0;
done:
@ -1272,11 +1088,8 @@ int
show_conf_xpath(clicon_handle h, cvec *cvv, cg_var *arg)
{
int retval = -1;
char *dbname;
char **vec = NULL;
char *str;
char *xpath;
yang_spec *yspec;
cg_var *cv;
cxobj *xt = NULL;
cxobj **xv = NULL;
@ -1288,23 +1101,13 @@ show_conf_xpath(clicon_handle h, cvec *cvv, cg_var *arg)
goto done;
}
/* Dont get attr here, take it from arg instead */
if (strcmp(str, "running") == 0) /* XXX: hardcoded */
dbname = clicon_running_db(h);
else
if (strcmp(str, "candidate") == 0) /* XXX: hardcoded */
dbname = clicon_candidate_db(h);
else{
clicon_err(OE_PLUGIN, 0, "No such db name: %s", vec[0]);
goto done;
}
if (dbname == NULL){
clicon_err(OE_FATAL, 0, "dbname not set");
if (strcmp(str, "running") != 0 && strcmp(str, "candidate") != 0){
clicon_err(OE_PLUGIN, 0, "No such db name: %s", str);
goto done;
}
cv = cvec_find_var(cvv, "xpath");
xpath = cv_string_get(cv);
yspec = clicon_dbspec_yang(h);
if (xmldb_get_vec(dbname, xpath, yspec, &xt, &xv, &xlen) < 0)
if (xmldb_get(h, str, xpath, 1, &xt, &xv, &xlen) < 0)
goto done;
for (i=0; i<xlen; i++)
clicon_xml2file(stdout, xv[i], 0, 1);

View file

@ -70,8 +70,6 @@ struct cli_handle {
/* ------ end of common handle ------ */
cligen_handle cl_cligen; /* cligen handle */
int cl_send2backend; /* Send changes to configuration daemon */
enum candidate_db_type cl_candidate_type;
cli_syntax_t *cl_stx; /* syntax structure */
};
@ -96,7 +94,6 @@ cli_handle_init(void)
}
cligen_userhandle_set(clih, cl);
cl->cl_cligen = clih;
cl->cl_candidate_type = CANDIDATE_DB_SHARED;
h = (clicon_handle)cl;
done:
return h;
@ -120,43 +117,8 @@ cli_handle_exit(clicon_handle h)
/*----------------------------------------------------------
* cli-specific handle access functions
*----------------------------------------------------------*/
/*! Send changes to configuration daemon or let client handle it itself. Default is 1 */
int
cli_set_send2backend(clicon_handle h, int send2backend)
{
struct cli_handle *cl = handle(h);
cl->cl_send2backend = send2backend;
return 0;
}
/*! Get status of whether to send changes to configuration daemon. */
int
cli_send2backend(clicon_handle h)
{
struct cli_handle *cl = handle(h);
return cl->cl_send2backend;
}
enum candidate_db_type
cli_candidate_type(clicon_handle h)
{
struct cli_handle *cl = handle(h);
return cl->cl_candidate_type;
}
int
cli_set_candidate_type(clicon_handle h, enum candidate_db_type type)
{
struct cli_handle *cl = handle(h);
cl->cl_candidate_type = type;
return 0;
}
/* Current syntax-group */
/*! Get current syntax-group */
cli_syntax_t *
cli_syntax(clicon_handle h)
{
@ -164,8 +126,10 @@ cli_syntax(clicon_handle h)
return cl->cl_stx;
}
/*! Set current syntax-group */
int
cli_syntax_set(clicon_handle h, cli_syntax_t *stx)
cli_syntax_set(clicon_handle h,
cli_syntax_t *stx)
{
struct cli_handle *cl = handle(h);
cl->cl_stx = stx;

View file

@ -56,7 +56,7 @@
#include "cli_handle.h"
/* Command line options to be passed to getopt(3) */
#define CLI_OPTS "hD:f:F:1u:d:m:cP:qpGLl:"
#define CLI_OPTS "hD:f:F:1u:d:m:qpGLl:"
/*! terminate cli application */
static int
@ -92,6 +92,7 @@ cli_signal_init (clicon_handle h)
}
/*! Interactive CLI command loop
* @param[in] h CLICON handle
* @see cligen_loop
*/
static void
@ -132,8 +133,6 @@ usage(char *argv0, clicon_handle h)
"\t-u <sockpath>\tconfig UNIX domain path (default: %s)\n"
"\t-d <dir>\tSpecify plugin directory (default: %s)\n"
"\t-m <mode>\tSpecify plugin syntax mode\n"
"\t-c \t\tWrite to candidate db directly, not via config backend\n"
"\t-P <dbname> \tWrite to private database\n"
"\t-q \t\tQuiet mode, dont print greetings or prompt, terminate on ctrl-C\n"
"\t-p \t\tPrint database yang specification\n"
"\t-G \t\tPrint CLI syntax generated from dbspec (if CLICON_CLI_GENMODEL enabled)\n"
@ -152,8 +151,6 @@ int
main(int argc, char **argv)
{
char c;
enum candidate_db_type dbtype;
char private_db[MAXPATHLEN];
int once;
char *tmp;
char *argv0 = argv[0];
@ -163,8 +160,8 @@ main(int argc, char **argv)
int logclisyntax = 0;
int help = 0;
char *treename;
char *running_db;
int logdst = CLICON_LOG_STDERR;
char *restarg; /* what remains after options */
/* Defaults */
@ -175,10 +172,7 @@ main(int argc, char **argv)
goto done;
if (cli_plugin_init(h) != 0)
goto done;
dbtype = CANDIDATE_DB_SHARED;
once = 0;
private_db[0] = '\0';
cli_set_send2backend(h, 1); /* send changes to config daemon */
cli_set_comment(h, '#'); /* Default to handle #! clicon_cli scripts */
/*
@ -269,13 +263,6 @@ main(int argc, char **argv)
usage(argv[0], h);
clicon_option_str_set(h, "CLICON_CLI_MODE", optarg);
break;
case 'c' : /* No config daemon (used in bootstrapping and file load) */
cli_set_send2backend(h, 0);
break;
case 'P' : /* load to private database with given name */
dbtype = CANDIDATE_DB_PRIVATE;
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", optarg); /* override default */
break;
case 'q' : /* Quiet mode */
clicon_option_str_set(h, "CLICON_QUIET", "on");
break;
@ -359,25 +346,12 @@ main(int argc, char **argv)
goto done;
}
/* Initialize databases */
if ((running_db = clicon_running_db(h)) == NULL)
goto done;
if (strlen(private_db))
clicon_option_str_set(h, "CLICON_CANDIDATE_DB", private_db);
if (!cli_send2backend(h))
if (xmldb_init(running_db) < 0){
fprintf (stderr, "FATAL: Could not init running_db. (Run as root?)\n");
goto done;
}
/* A client does not have access to the candidate (and running)
databases if both these conditions are true:
1. clicon_sock_family(h) == AF_INET[6]
2. cli_send2backend(h) == 1
*/
if (clicon_sock_family(h) == AF_UNIX || cli_send2backend(h)==0)
if (init_candidate_db(h, dbtype) < 0)
if (clicon_sock_family(h) == AF_UNIX)
if (init_candidate_db(h) < 0)
return -1;
if (logclisyntax)
@ -386,19 +360,29 @@ main(int argc, char **argv)
if (debug)
clicon_option_dump(h, debug);
/* Join rest of argv to a single command */
restarg = clicon_strjoin(argc, argv, " ", __FUNCTION__);
/* Call start function in all plugins before we go interactive
Pass all args after the standard options to plugin_start
*/
tmp = *(argv-1);
*(argv-1) = argv0;
cli_plugin_start(h, argc+1, argv-1);
*(argv-1) = tmp;
/* Launch interfactive event loop, unless -1 */
if (once == 0)
if (restarg != NULL && strlen(restarg)){
char *mode = cli_syntax_mode(h);
int result;
clicon_parse(h, restarg, &mode, &result);
}
/* Go into event-loop unless -1 command-line */
if (!once)
cli_interactive(h);
done:
unchunk_group(__FUNCTION__);
// Gets in your face if we log on stderr
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());

View file

@ -31,18 +31,6 @@
#define CLI_PROMPT_LEN 64
#define CLI_DEFAULT_PROMPT ">"
/*
* Types
*/
//typedef void *cli_handle; /* clicon cli handle, see struct cli_handle */
enum candidate_db_type{
CANDIDATE_DB_NONE, /* No candidate */
CANDIDATE_DB_PRIVATE, /* Create a private candidate_db */
CANDIDATE_DB_SHARED, /* Share the candidate with everyone else */
CANDIDATE_DB_CURRENT /* Dont create candidate, use current directly */
};
/*
* Function Declarations
*/
@ -62,16 +50,12 @@ char cli_set_comment(clicon_handle h, char c);
char cli_comment(clicon_handle h);
int cli_set_exiting(clicon_handle h, int exiting);
int cli_exiting(clicon_handle h);
int cli_set_send2backend(clicon_handle h, int send2backend);
int cli_send2backend(clicon_handle h);
clicon_handle cli_handle_init(void);
int cli_handle_exit(clicon_handle h);
cligen_handle cli_cligen(clicon_handle h);
enum candidate_db_type cli_candidate_type(clicon_handle h);
int cli_set_candidate_type(clicon_handle h, enum candidate_db_type type);
/* cli_common.c */
int init_candidate_db(clicon_handle h, enum candidate_db_type type);
int init_candidate_db(clicon_handle h);
int exit_candidate_db(clicon_handle h);
#define cli_output cligen_output
int cli_set (clicon_handle h, cvec *vars, cg_var *arg);

View file

@ -50,7 +50,7 @@
#include <clixon/clixon.h>
/* Command line options to be passed to getopt(3) */
#define DBCTRL_OPTS "hDd:pbn:r:m:Zi"
#define DBCTRL_OPTS "hDSd:pbn:r:m:Zi"
/*
* remove_entry
@ -65,8 +65,7 @@ remove_entry(char *dbname, char *key)
#endif
}
/*
* usage
/*! usage
*/
static void
usage(char *argv0)
@ -75,7 +74,8 @@ usage(char *argv0)
"where options are\n"
"\t-h\t\tHelp\n"
"\t-D\t\tDebug\n"
"\t-d <dbname>\tDatabase name (default: running_db)\n"
"\t-S\t\tLog on syslog\n"
"\t-d <db>\tDatabase name (default: running)\n"
"\t-p\t\tDump database on stdout\n"
"\t-b\t\tBrief output, just print keys. Combine with -p or -m\n"
"\t-n \"<key> <val>\" Add database entry\n"
@ -101,9 +101,8 @@ main(int argc, char **argv)
char *addstr;
char rmkey[MAXPATHLEN];
int brief;
char dbname[MAXPATHLEN] = {0,};
char db[MAXPATHLEN] = {0,};
int use_syslog;
yang_spec *yspec;
clicon_handle h;
/* In the startup, logs to stderr & debug flag set later */
@ -118,6 +117,7 @@ main(int argc, char **argv)
brief = 0;
use_syslog = 0;
addstr = NULL;
memcpy(db, "running", strlen("running")+1);
memset(rmkey, '\0', sizeof(rmkey));
if ((h = clicon_handle_init()) == NULL)
@ -143,6 +143,7 @@ main(int argc, char **argv)
use_syslog?CLICON_LOG_SYSLOG:CLICON_LOG_STDERR);
clicon_debug_init(debug, NULL);
/* Now rest of options */
optind = 1;
while ((c = getopt(argc, argv, DBCTRL_OPTS)) != -1)
@ -159,8 +160,8 @@ main(int argc, char **argv)
case 'b': /* Dump/print/match database brief (combone w -p or -m) */
brief++;
break;
case 'd': /* dbname */
if (!optarg || sscanf(optarg, "%s", dbname) != 1)
case 'd': /* db either db filename or symbolic: running|candidate */
if (!optarg || sscanf(optarg, "%s", db) != 1)
usage(argv[0]);
break;
case 'n': /* add database entry */
@ -189,33 +190,32 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (*dbname == '\0'){
if (*db == '\0'){
clicon_err(OE_FATAL, 0, "database not specified (with -d <db>): %s");
goto done;
}
yspec = clicon_dbspec_yang(h);
if (dumpdb){
if (xmldb_dump(stdout, dbname, matchkey)) {
/* Here db must be local file-path */
if (xmldb_dump(stdout, db, matchkey)) {
fprintf(stderr, "Match error\n");
goto done;
}
}
if (addent) /* add entry */
if (xmldb_put_xkey(dbname, addstr, NULL, yspec, OP_REPLACE) < 0)
if (xmldb_put_xkey(h, db, addstr, NULL, OP_REPLACE) < 0)
goto done;
if (rment)
if (remove_entry(dbname, rmkey) < 0)
if (remove_entry(db, rmkey) < 0)
goto done;
if (zapdb) /* remove databases */
/* XXX This assumes direct access to database */
if (unlink(dbname) < 0){
clicon_err(OE_FATAL, errno, "unlink %s", dbname);
if (xmldb_delete(h, db) < 0){
clicon_err(OE_FATAL, errno, "xmldb_delete %s", db);
goto done;
}
if (initdb)
if (xmldb_init(dbname) < 0)
if (xmldb_init(h, db) < 0)
goto done;
done:
return 0;
}

View file

@ -173,56 +173,25 @@ detect_endtag(char *tag, char ch, int *state)
return retval;
}
/*
* target_locked
* return 1 if locked, 0 if not.
* return clientid if locked.
*/
int
target_locked(enum target_type target, int *client)
{
return 0;
}
/*
* unlock_target
*/
int
unlock_target(enum target_type target)
{
return 0;
}
int
lock_target(enum target_type target)
{
return 0;
}
/*! Get "target" attribute, return actual database given candidate or running
* Caller must do error handling
* @retval dbname Actual database file name
*/
char *
netconf_get_target(clicon_handle h, cxobj *xn, char *path)
netconf_get_target(clicon_handle h,
cxobj *xn,
char *path)
{
cxobj *x;
char *target = NULL;
char *running_db;
char *candidate_db;
if ((running_db = clicon_running_db(h)) == NULL)
goto done;
if ((candidate_db = clicon_candidate_db(h)) == NULL)
goto done;
if ((x = xpath_first(xn, path)) != NULL){
if (xpath_first(x, "candidate") != NULL)
target = candidate_db;
target = "candidate";
else
if (xpath_first(x, "running") != NULL)
target = running_db;
if (xpath_first(x, "running") != NULL)
target = "running";
}
done:
return target;
}

View file

@ -61,11 +61,11 @@
/*! Process incoming packet
* @param[in] h Clicon handle
* @param[in] xf Packet buffer
* @param[in] cb Packet buffer
*/
static int
process_incoming_packet(clicon_handle h,
cbuf *xf)
cbuf *cb)
{
char *str;
char *str0;
@ -76,23 +76,23 @@ process_incoming_packet(clicon_handle h,
cbuf *xf1;
clicon_debug(1, "RECV");
clicon_debug(2, "%s: RCV: \"%s\"", __FUNCTION__, cbuf_get(xf));
if ((str0 = strdup(cbuf_get(xf))) == NULL){
clicon_debug(2, "%s: RCV: \"%s\"", __FUNCTION__, cbuf_get(cb));
if ((str0 = strdup(cbuf_get(cb))) == NULL){
clicon_log(LOG_ERR, "%s: strdup: %s", __FUNCTION__, strerror(errno));
return -1;
}
str = str0;
/* Parse incoming XML message */
if (clicon_xml_parse_string(&str, &xml_req) < 0){
if ((xf = cbuf_new()) == NULL){
netconf_create_rpc_error(xf, NULL,
if ((cb = cbuf_new()) == NULL){
netconf_create_rpc_error(cb, NULL,
"operation-failed",
"rpc", "error",
NULL,
NULL);
netconf_output(1, xf, "rpc-error");
cbuf_free(xf);
netconf_output(1, cb, "rpc-error");
cbuf_free(cb);
}
else
clicon_log(LOG_ERR, "%s: cbuf_new", __FUNCTION__);
@ -181,12 +181,12 @@ netconf_input_cb(int s,
unsigned char buf[BUFSIZ];
int i;
int len;
static cbuf *xf; /* XXX: should use ce state? */
static cbuf *cb; /* XXX: should use ce state? */
int xml_state = 0;
int retval = -1;
if (xf == NULL)
if ((xf = cbuf_new()) == NULL){
if (cb == NULL)
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "%s: cbuf_new", __FUNCTION__);
return retval;
}
@ -209,22 +209,22 @@ netconf_input_cb(int s,
for (i=0; i<len; i++){
if (buf[i] == 0)
continue; /* Skip NULL chars (eg from terminals) */
cprintf(xf, "%c", buf[i]);
cprintf(cb, "%c", buf[i]);
if (detect_endtag("]]>]]>",
buf[i],
&xml_state)) {
/* OK, we have an xml string from a client */
if (process_incoming_packet(h, xf) < 0){
if (process_incoming_packet(h, cb) < 0){
goto done;
}
if (cc_closed)
break;
cbuf_reset(xf);
cbuf_reset(cb);
}
}
retval = 0;
done:
// cbuf_free(xf);
// cbuf_free(cb);
if (cc_closed)
retval = -1;
return retval;
@ -255,16 +255,15 @@ send_hello(int s)
return retval;
}
/* from init_candidate_db() and clicon_rpc_copy() */
/*! Initialize candidate database */
static int
init_candidate_db(clicon_handle h, char *running_db, char *candidate_db)
init_candidate_db(clicon_handle h)
{
struct stat sb;
int retval = -1;
/* init shared candidate */
if (lstat(candidate_db, &sb) < 0){
if (clicon_rpc_copy(h, running_db, candidate_db) < 0)
if (xmldb_exists(h, "candidate") != 1){
if (xmldb_copy(h, "running", "candidate") < 0)
goto done;
}
retval = 0;
@ -316,8 +315,6 @@ main(int argc, char **argv)
int quiet = 0;
clicon_handle h;
int use_syslog;
char *running_db;
char *candidate_db;
/* Defaults */
use_syslog = 0;
@ -390,15 +387,7 @@ main(int argc, char **argv)
if (netconf_plugin_load(h) < 0)
return -1;
if ((running_db = clicon_running_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "running db not set");
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
clicon_err(OE_FATAL, 0, "candidate db not set");
goto done;
}
if (init_candidate_db(h, running_db, candidate_db) < 0)
if (init_candidate_db(h) < 0)
return -1;
/* Call start function is all plugins before we go interactive */
tmp = *(argv-1);

View file

@ -108,14 +108,13 @@ netconf_filter_xmldb(clicon_handle h,
cxobj *xc;
cxobj *xfilterconf = NULL;
int retval = -1;
yang_spec *ys = clicon_dbspec_yang(h);
char *selector;
/* Default subtree filter */
switch (foption){
case FILTER_SUBTREE:
/* Get the whole database as xml */
if (xmldb_get(source, NULL, ys, &xdb) < 0){
if (xmldb_get(h, source, NULL, 0, &xdb, NULL, NULL) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"application",
@ -154,7 +153,7 @@ netconf_filter_xmldb(clicon_handle h,
break;
case FILTER_XPATH:
selector = xml_find_value(xfilter, "select");
if (xmldb_get(source, selector, ys, &xdb) < 0){
if (xmldb_get(h, source, selector, 0, &xdb, NULL, NULL) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"application",
@ -202,13 +201,13 @@ netconf_filter_xmldb(clicon_handle h,
<get-config>
<source>
<( candidate | running )/>
<candidate/> | <running/>
</source>
</get-config>
<get-config>
<source>
<( candidate | running )/>
<candidate/> | <running/>
</source>
<filter type="subtree">
<configuration>
@ -220,24 +219,6 @@ netconf_filter_xmldb(clicon_handle h,
<rpc><get-config><source><running /></source>
<filter type="xpath" select="//SenderTwampIpv4"/>
</get-config></rpc>]]>]]>
* Call graph, client to backend and formats
* netconf_input_cb # client
* read
* process_incoming_packet #
* clicon_xml_parse_string #
* netconf_rpc_dispatch
* netconf_get_config #
* xpath_first
* netconf_filter #
* db2xml_key # "^.*$"
* clicon_dbitems # (db)
* db_regexp # (lvec)
* lvec2cvec # (cvec)
* cvec2xml # (xml)
* clicon_xml2cbuf # (xml->char*)
* wanted:
* netconf_get_config
* xpath(db, filter)
*/
int
netconf_get_config(clicon_handle h,
@ -276,7 +257,7 @@ netconf_get_config(clicon_handle h,
/*! Get options from netconf edit-config
* <edit-config>
* <config>XXX</config>
* <config>...</config>
* <default-operation>(merge | none | replace)</default-operation>
* <error-option>(stop-on-error | continue-on-error )</error-option>
* <test-option>(set | test-then-set | test-only)</test-option>
@ -418,20 +399,12 @@ netconf_edit_config(clicon_handle h,
cxobj *xc; /* config */
cxobj *xcc; /* child of config */
char *target; /* db */
char *candidate_db;
cbuf *cbxml = NULL;
char *xmlstr;
if ((candidate_db = clicon_candidate_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error");
goto done;
}
/* must have target, and it should be candidate */
if ((target = netconf_get_target(h, xn, "target")) == NULL ||
strcmp(target, candidate_db)){
strcmp(target, "candidate")){
netconf_create_rpc_error(cb_err, xorig,
"missing-element",
"protocol",
@ -532,7 +505,7 @@ netconf_copy_config(clicon_handle h,
goto done;
}
#endif
if (clicon_rpc_copy(h, source, target) < 0){
if (xmldb_copy(h, source, target) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
@ -546,7 +519,7 @@ netconf_copy_config(clicon_handle h,
return retval;
}
/*
/*! Delete configuration
<delete-config>
<target>
<candidate/>
@ -564,15 +537,6 @@ netconf_delete_config(clicon_handle h,
{
char *target; /* filenames */
int retval = -1;
char *candidate_db;
if ((candidate_db = clicon_candidate_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error");
goto done;
}
if ((target = netconf_get_target(h, xn, "target")) == NULL){
netconf_create_rpc_error(cb_err, xorig,
@ -583,7 +547,7 @@ netconf_delete_config(clicon_handle h,
"<bad-element>target</bad-element>");
goto done;
}
if (strcmp(target, candidate_db)){
if (strcmp(target, "candidate")){
netconf_create_rpc_error(cb_err, xorig,
"bad-element",
"protocol",
@ -592,14 +556,14 @@ netconf_delete_config(clicon_handle h,
"<bad-element>target</bad-element>");
goto done;
}
if (clicon_rpc_rm(h, target) < 0){
if (xmldb_delete(h, target) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error");
goto done;
}
if (clicon_rpc_initdb(h, target) < 0){
if (xmldb_init(h, target) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
@ -612,7 +576,7 @@ netconf_delete_config(clicon_handle h,
return retval;
}
/*
/*! Close a (user) session
<close-session/>
*/
int
@ -626,12 +590,13 @@ netconf_close_session(cxobj *xn,
return 0;
}
/*
/*! Lock a database
<lock>
<target>
<candidate/>
</target>
</lock>
XXX
*/
int
netconf_lock(clicon_handle h,
@ -652,40 +617,20 @@ netconf_lock(clicon_handle h,
"<bad-element>source</bad-element>");
goto done;
}
#ifdef notyet
if (target_locked(&client) > 0){
snprintf(info, 64, "<session-id>%d</session-id>", client);
netconf_create_rpc_error(cb_err, xorig,
"lock-denied",
"protocol",
"error",
"Lock failed, lock is already held",
info);
return -1;
}
if (lock_target(target) < 0){
netconf_create_rpc_error(cb_err, xorig,
"lock-denied",
"protocol",
"error",
"Lock failed, lock is already held",
NULL);
return -1;
}
#endif
netconf_ok_set(1);
retval = 0;
done:
return retval;
}
/*
/*! Unlock a database
<unlock>
<target>
<candidate/>
</target>
</unlock>
XXX
*/
int
netconf_unlock(clicon_handle h,
@ -705,47 +650,18 @@ netconf_unlock(clicon_handle h,
"<bad-element>target</bad-element>");
goto done;
}
#ifdef notyet
if (target_locked(&client) == 0){
netconf_create_rpc_error(cb_err, xorig,
"lock-denied",
"protocol",
"error",
"Unlock failed, lock is not held",
NULL);
return -1;
}
if (client != ce_nr){
snprintf(info, 64, "<session-id>%d</session-id>", client);
netconf_create_rpc_error(cb_err, xorig,
"lock-denied",
"protocol",
"error",
"Unlock failed, lock is held by other entity",
info);
return -1;
}
if (unlock_target(target) < 0){
netconf_create_rpc_error(cb_err, xorig,
"lock-denied",
"protocol",
"error",
"Unlock failed, unkown reason",
NULL);
return -1;
}
#endif /* notyet */
/* XXX notyet */
netconf_ok_set(1);
retval = 0;
done:
return retval;
}
/*
/*! Kill other user sessions
<kill-session>
<session-id>PID</session-id>
</kill-session>
XXX
*/
int
netconf_kill_session(cxobj *xn, cbuf *cb, cbuf *cb_err, cxobj *xorig)
@ -793,7 +709,7 @@ netconf_kill_session(cxobj *xn, cbuf *cb, cbuf *cb_err, cxobj *xorig)
return 0;
}
/*
/*! Commit candidate -> running
<commit/>
:candidate
*/
@ -805,25 +721,8 @@ netconf_commit(clicon_handle h,
cxobj *xorig)
{
int retval = -1;
char *candidate_db;
char *running_db;
if ((candidate_db = clicon_candidate_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error: candidate not set");
goto done;
}
if ((running_db = clicon_running_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error: running not set");
goto done;
}
if (clicon_rpc_commit(h, candidate_db,
running_db,
if (clicon_rpc_commit(h, "candidate", "running",
1, 1) < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
@ -838,7 +737,7 @@ netconf_commit(clicon_handle h,
return retval;
}
/*
/*! Discard all changes in candidate / revert to running
<discard-changes/>
:candidate
*/
@ -850,24 +749,8 @@ netconf_discard_changes(clicon_handle h,
cxobj *xorig)
{
int retval = -1;
char *running_db;
char *candidate_db;
if ((running_db = clicon_running_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error: running not set");
goto done;
}
if ((candidate_db = clicon_candidate_db(h)) == NULL){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
NULL, "Internal error");
goto done;
}
if (clicon_rpc_copy(h, running_db, candidate_db) < 0){
if (xmldb_copy(h, "running", "candidate") < 0){
netconf_create_rpc_error(cb_err, xorig,
"operation-failed",
"protocol", "error",
@ -881,7 +764,7 @@ netconf_discard_changes(clicon_handle h,
return retval;
}
/*
/*! Check the semantic consistency of candidate
<validate/>
:validate
*/