Example #1
0
/* alloc help-function: double xv vectors. spcial case for init */
static int
xv_alloc(struct xml_node ***xv0p, struct xml_node ***xv1p, int *xv_maxp)
{
    struct xml_node **xv0     = *xv0p;
    struct xml_node **xv1     = *xv1p;
    int               xv_max0 = *xv_maxp;
    int               xv_max;
    int               init;

    init = (xv0p == NULL);
    if (init)
	xv_max = xv_max0;
    else
	xv_max = 2*xv_max0;
    if ((xv0 = realloc(xv0, sizeof(struct xml_node *) * xv_max)) == NULL){
	clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
	return -1;
    }
    if (init)
	memset(xv0, 0, xv_max);
    else
	memset(xv0+xv_max0, 0, xv_max-xv_max0);
    if ((xv1 = realloc(xv1, sizeof(struct xml_node *) * xv_max)) == NULL){
	clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
	return -1;
    }
    if (init)
	memset(xv1, 0, xv_max);
    else
	memset(xv1+xv_max0, 0, xv_max-xv_max0);
    *xv0p = xv0;
    *xv1p = xv1;
    *xv_maxp = xv_max;
    return 0;
}
Example #2
0
/*! Delete all elements in a database 
 * Utility function used by cligen spec file
 */
int
delete_all(clicon_handle h, 
	   cvec         *cvv, 
	   cvec         *argv)
{
    char            *dbstr;
    int              retval = -1;

    if (cvec_len(argv) != 1){
	clicon_err(OE_PLUGIN, 0, "Requires one element: dbname");
	goto done;
    }
    dbstr = cv_string_get(cvec_i(argv, 0));
    if (strcmp(dbstr, "running") != 0 && 
	strcmp(dbstr, "candidate") != 0 &&
	strcmp(dbstr, "startup") != 0){
	clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);	
	goto done;
    }
    if (clicon_rpc_delete_config(h, dbstr) < 0)
	goto done;
    retval = 0;
  done:
    return retval;
}
Example #3
0
char *
clicon_sha1hex(const char *str)
{
    int i;
    char *retstr;
    SHA1Context context;
    

    SHA1Reset(&context);
    SHA1Input(&context, (const unsigned char *)str, strlen(str));
    if (!SHA1Result(&context)) {
	clicon_err(OE_UNIX, 0, "Could not compute SHA1 message digest");
	return NULL;
    }
    
    /* 160 bits = 20 bytes = 40 hexdigits + '\0' */
    if ((retstr = malloc(41)) == NULL) {
	clicon_err(OE_UNIX, errno, "malloc");
	return NULL;
    }
    
    for(i = 0; i < 5 ; i++)
	sprintf(retstr + (i*8), "%.8x", context.Message_Digest[i]);
    
    return retstr;
}
Example #4
0
File: system.c Project: clicon/rost
/*
 * Read procut number and serialnr from product file, and set environment vars:
 * typically RNR_PRODUCT and RNR_SERIALNR
 * Then call the rost_get_ functions above
 */
int
rost_product2env()
{
    FILE *f;
    char line[1024];
    char *name, *val;

    if (is_initialized)
	return 0;

    if ((f = fopen (ROST_PRODUCT_FILE, "r")) == NULL){
#if 0 /* ignored */
        clicon_err(OE_UNIX, errno, "Failed to open %s", ROST_PRODUCT_FILE);
        return -1;
#else
	return 0;
#endif
    }
    while (fgets(line, sizeof(line), f) != NULL){
	line[strlen(line)-1] = '\0';
	val = line;
	name = strsep(&val, "=");
	if (setenv(name, val, 1) < 0){
	    clicon_err(OE_UNIX, errno, "setenv");
	    return -1;
	}
    }
    fclose(f);
    is_initialized = 1;

    return 0;
}
Example #5
0
/*! Compare two dbs using XML. Write to file and run diff
 */
static int
compare_xmls(cxobj *xc1, 
	     cxobj *xc2, 
	     int    astext)
{
    int    fd;
    FILE  *f;
    char   filename1[MAXPATHLEN];
    char   filename2[MAXPATHLEN];
    char   cmd[MAXPATHLEN];
    int    retval = -1;
    cxobj *xc;

    snprintf(filename1, sizeof(filename1), "/tmp/cliconXXXXXX");
    snprintf(filename2, sizeof(filename2), "/tmp/cliconXXXXXX");
    if ((fd = mkstemp(filename1)) < 0){
	clicon_err(OE_UNDEF, errno, "tmpfile: %s", strerror (errno));
	goto done;
    }
    if ((f = fdopen(fd, "w")) == NULL)
	goto done;
    xc = NULL;
    if (astext)
	while ((xc = xml_child_each(xc1, xc, -1)) != NULL)
	    xml2txt(f, xc, 0);
    else
	while ((xc = xml_child_each(xc1, xc, -1)) != NULL)
	    xml_print(f, xc);

    fclose(f);
    close(fd);

    if ((fd = mkstemp(filename2)) < 0){
	clicon_err(OE_UNDEF, errno, "mkstemp: %s", strerror (errno));
	goto done;
    }
    if ((f = fdopen(fd, "w")) == NULL)
	goto done;
    xc = NULL;
    if (astext)
	while ((xc = xml_child_each(xc2, xc, -1)) != NULL)
	    xml2txt(f, xc, 0);
    else
	while ((xc = xml_child_each(xc2, xc, -1)) != NULL)
	    xml_print(f, xc);
    fclose(f);
    close(fd);

    snprintf(cmd, sizeof(cmd), "/usr/bin/diff -dU 1 %s %s |  grep -v @@ | sed 1,2d", 		 filename1, filename2);
    if (system(cmd) < 0)
	goto done;

    retval = 0;
  done:
    unlink(filename1);
    unlink(filename2);
    return retval;
}
Example #6
0
/*! Register log notification stream
 * @param[in] h       Clicon handle
 * @param[in] stream  Event stream. CLICON is predefined, others are application-defined
 * @param[in] filter  Filter. For xml notification ie xpath: .[name="kalle"]
 * @param[in] status  0 for stop, 1 to start
 * @param[in] fn      Callback function called when notification occurs
 * @param[in] arg     Argument to function note
 * Note this calls cligen_regfd which may callback on cli command interpretator
 */
int
cli_notification_register(clicon_handle    h, 
			  char            *stream, 
			  enum format_enum format,
			  char            *filter, 
			  int              status, 
			  int            (*fn)(int, void*),
			  void            *arg)
{
    int              retval = -1;
    char            *logname = NULL;
    void            *p;
    int              s;
    clicon_hash_t   *cdat = clicon_data(h);
    size_t           len;
    int              s_exist = -1;

    len = strlen("log_socket_") + strlen(stream) + 1;
    if ((logname = malloc(len)) == NULL){
	clicon_err(OE_UNIX, errno, "malloc");
	goto done;
    }	
    snprintf(logname, len, "log_socket_%s", stream);
    if ((p = hash_value(cdat, logname, &len)) != NULL)
	s_exist = *(int*)p;

    if (status){ /* start */
	if (s_exist!=-1){
	    clicon_err(OE_PLUGIN, 0, "Result log socket already exists");
	    goto done;
	}
	if (clicon_rpc_create_subscription(h, stream, filter, &s) < 0)
	    goto done;
	if (cligen_regfd(s, fn, arg) < 0)
	    goto done;
	if (hash_add(cdat, logname, &s, sizeof(s)) == NULL)
	    goto done;
    }
    else{ /* stop */
	if (s_exist != -1){
	    cligen_unregfd(s_exist);
	}
	hash_del(cdat, logname);
#if 0 /* cant turn off */
	if (clicon_rpc_create_subscription(h, status, stream, format, filter, NULL) < 0)
	    goto done;
#endif
    }
    retval = 0;
  done:
    if (logname)
	free(logname);
    return retval;
}
Example #7
0
/*! Make a notify subscription to backend and un/register callback for return messages.
 * 
 * @param[in] h      Clicon handle
 * @param[in] cvv    Not used
 * @param[in] arg    A string with <log stream name> <stream status> [<format>]
 * where <status> is "0" or "1"
 * and   <format> is XXX
 * Example code: Start logging of mystream and show logs as xml
 * @code
 * cmd("comment"), cli_notify("mystream","1","xml"); 
 * @endcode
 * XXX: format is a memory leak
 */
int
cli_notify(clicon_handle h, 
	   cvec         *cvv, 
	   cvec         *argv)
{
    char            *stream = NULL;
    int              retval = -1;
    int              status;
    char            *formatstr = NULL;
    enum format_enum format = FORMAT_TEXT;

    if (cvec_len(argv) != 2 && cvec_len(argv) != 3){
	clicon_err(OE_PLUGIN, 0, "Requires arguments: <logstream> <status> [<format>]");
	goto done;
    }
    stream = cv_string_get(cvec_i(argv, 0));
    status  = atoi(cv_string_get(cvec_i(argv, 1)));
    if (cvec_len(argv) > 2){
	formatstr = cv_string_get(cvec_i(argv, 2));
	format = format_str2int(formatstr);
    }
    if (cli_notification_register(h, 
				  stream, 
				  format,
				  "", 
				  status, 
				  cli_notification_cb, 
				  (void*)format) < 0)
	goto done;

    retval = 0;
  done:
    return retval;
}
Example #8
0
/*! Send a debug request to backend server
 * @param[in] h        CLICON handle
 * @param[in] level    Debug level
 * @retval    0        OK
 * @retval   -1        Error and logged to syslog
 */
int
clicon_rpc_debug(clicon_handle h, 
		int           level)
{
    int                retval = -1;
    struct clicon_msg *msg = NULL;
    cxobj             *xret = NULL;
    cxobj             *xerr;
    char              *username;

    username = clicon_username_get(h);
    /* XXX: hardcoded example yang, should be clixon-config!!! */
    if ((msg = clicon_msg_encode("<rpc username=\"%s\"><debug xmlns=\"http://clicon.org/lib\"><level>%d</level></debug></rpc>", username?username:"", level)) == NULL)
	goto done;
    if (clicon_rpc_msg(h, msg, &xret, NULL) < 0)
	goto done;
    if ((xerr = xpath_first(xret, "//rpc-error")) != NULL){
	clicon_rpc_generate_error("Debug",xerr);
	goto done;
    }
    if (xpath_first(xret, "//rpc-reply/ok") == NULL){
	clicon_err(OE_XML, 0, "rpc error"); /* XXX extract info from rpc-error */
	goto done;
    }
    retval = 0;
 done:
    if (msg)
	free(msg);
    if (xret)
	xml_free(xret);
    return retval;
}
Example #9
0
/*
 * plugin call
 */
static int
plugin_call(clicon_handle h, char *func)
{
    int retval = -1;
    PyObject *handle = NULL;
    PyObject *cli = NULL;
    PyObject *val = NULL;
    
    if (Py_IsInitialized() == 0)
	return 0;

    PyErr_Clear();
    if ((cli = PyImport_ImportModule("cliconcli")) == NULL)
	goto quit;
    
    if ((handle = PyCapsule_New((void *)h, NULL, NULL)) == NULL)
	goto quit;
    
    val = PyObject_CallMethod(cli, func, "O", handle);
    if (val == NULL)
	goto quit;
    
    retval = PyLong_AsLong(val);

quit:
    if (PyErr_Occurred())
	clicon_err(OE_PLUGIN, 0, "%s", ErrStringVerbose(0));
    Py_XDECREF(cli);
    Py_XDECREF(handle);
    Py_XDECREF(val);

    return retval;
}
Example #10
0
/*! Merge xml in filename into database
 * @retval   -1       Error
 * @retval    0       Validation failed (with cbret set)
 * @retval    1       Validation OK       
 */
static int
load_extraxml(clicon_handle h,
	      char         *filename,
	      const char   *db,
	      cbuf         *cbret)
{
    int    retval =  -1;
    cxobj *xt = NULL;
    int    fd = -1;

    if (filename == NULL)
	return 1;
    if ((fd = open(filename, O_RDONLY)) < 0){
	clicon_err(OE_UNIX, errno, "open(%s)", filename);
	goto done;
    }
    if (xml_parse_file(fd, "</config>", NULL, &xt) < 0)
	goto done;
    /* Replace parent w first child */
    if (xml_rootchild(xt, 0, &xt) < 0)
	goto done;
    /* Merge user reset state */
    retval = xmldb_put(h, (char*)db, OP_MERGE, xt, clicon_username_get(h), cbret);
 done:
    if (fd != -1)
	close(fd);
    if (xt)
	xml_free(xt);
    return retval;
}
Example #11
0
/*! Unload all plugins: call exit function and close shared handle
 * @param[in]  h       Clicon handle
 */
int
clixon_plugin_exit(clicon_handle h)
{
    clixon_plugin *cp;
    plgexit_t     *exitfn;
    int            i;
    char          *error;
    
    for (i = 0; i < _clixon_nplugins; i++) {
	cp = &_clixon_plugins[i];
	if ((exitfn = cp->cp_api.ca_exit) == NULL)
	    continue;
	if (exitfn(h) < 0) {
	    clicon_debug(1, "plugin_exit() failed");
	    return -1;
	}
	if (dlclose(cp->cp_handle) != 0) {
	    error = (char*)dlerror();
	    clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
	}
    }
    if (_clixon_plugins){
	free(_clixon_plugins);
	_clixon_plugins = NULL;
    }
    _clixon_nplugins = 0;
    return 0;
}
Example #12
0
/*! Generate and log clicon error function call from Netconf error message
 * @param[in]  xerr    Netconf error message on the level: <rpc-reply><rpc-error>
 */
int
clicon_rpc_generate_error(char  *format, 
			  cxobj *xerr)
{
    int    retval = -1;
    cbuf  *cb = NULL;
    cxobj *x;

    if ((cb = cbuf_new()) ==NULL){
	clicon_err(OE_XML, errno, "cbuf_new");
	goto done;
    }
    if ((x=xpath_first(xerr, "error-type"))!=NULL)
	cprintf(cb, "%s ", xml_body(x));
    if ((x=xpath_first(xerr, "error-tag"))!=NULL)
	cprintf(cb, "%s ", xml_body(x));
    if ((x=xpath_first(xerr, "error-message"))!=NULL)
	cprintf(cb, "%s ", xml_body(x));
    if ((x=xpath_first(xerr, "error-info"))!=NULL)
	clicon_xml2cbuf(cb, xml_child_i(x,0), 0, 0);
    clicon_log(LOG_ERR, "%s: %s", format, cbuf_get(cb));
    retval = 0;
 done:
    if (cb)
	cbuf_free(cb);
    return retval;
}
Example #13
0
/*! Clixon startup startup mode: Commit startup configuration into running state
 * @param[in]  h       Clixon handle
 * @param[in]  db      tmp or startup
 * @param[out] cbret   If status is invalid contains error message
 * @retval    -1       Error
 * @retval     0       Validation failed
 * @retval     1       OK

OK:
                              reset     
running                         |--------+------------> RUNNING
                parse validate OK       / commit 
startup -------+--+-------+------------+          


INVALID (requires manual edit of candidate)
failsafe      ----------------------+
                            reset    \ commit
running                       |-------+---------------> RUNNING FAILSAFE
              parse validate fail 
startup      ---+-------------------------------------> INVALID XML

ERR: (requires repair of startup) NYI
failsafe      ----------------------+
                            reset    \ commit
running                       |-------+---------------> RUNNING FAILSAFE
              parse fail
startup       --+-------------------------------------> BROKEN XML

 * @note: if commit fails, copy factory to running
 */
int
startup_mode_startup(clicon_handle        h,
		     char                *db,
		     cbuf                *cbret)
{
    int         retval = -1;
    int         ret;
    
    if (strcmp(db, "running")==0){
	clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
	goto done;
    }
    /* Load plugins and call plugin_init() */
    if (backend_plugin_initiate(h) != 0) 
	goto done;
    /* If startup does not exist, create it empty */
    if (xmldb_exists(h, db) != 1){ /* diff */
	if (xmldb_create(h, db) < 0) /* diff */
	    return -1;
    }
    if ((ret = startup_commit(h, db, cbret)) < 0)
	goto done;
    if (ret == 0)
	goto fail;
    retval = 1;
 done:
    return retval;
 fail:
    retval = 0;
    goto done;
}
Example #14
0
File: system.c Project: clicon/rost
/*!
 * \brief Special error message for quagga routing, using clicon_err as backend
 *
 * This is a kludge to replace clicon_err(OE_ROUTING..) calls with 
 * application-specific code inside clicon. We have now moved it outside 
 * of clicon and placed it here instead.
 */
int
rost_err(int suberr, char *reason, ...)
{
    va_list        args;
    struct errvec *ev;
    char          *errstr;
    int            len;
    char          *msg = NULL;
    int            retval = -1;

    for (ev=QV; ev->ev_err != -1; ev++)
	if (ev->ev_err == suberr)
	    break;
    errstr = ev?(ev->ev_str?ev->ev_str:"unknown"):"ROST unknown error";

    /* first round: compute length of error message */
    va_start(args, reason);
    len = vsnprintf(NULL, 0, reason, args);
    va_end(args);
    
    /* Allocate message buffer */
    if ((msg = malloc(len+1)) == NULL) {
	clicon_err(OE_UNIX, errno, "malloc");
	goto done;
    }

    /* second round: compute write message from reason and args */
    va_start(args, reason);
    if (vsnprintf(msg, len+1, reason, args) < 0){
	va_end(args);
	fprintf(stderr, "vsnprintf: %s\n", strerror(errno)); /* dont use clicon_err here due to recursion */
	goto done;
    }
    va_end(args);
    retval = clicon_err(OE_ROUTING, 0, "%s: %s", 
		      msg,
		      errstr);
  done:
    if (msg)
	free(msg);
    return retval;
}
Example #15
0
File: system.c Project: clicon/rost
/*
 * XXX: avoid /proc
 */
int
rost_uptime(int *sec)
{
    FILE *f;
    double u; /* seconds */

    /* Open /proc filesystem */
    if ((f = fopen ("/proc/uptime", "r")) == NULL){
        clicon_err(OE_UNIX, errno, "Failed to open /proc/uptime");
        return -1;
    }
    if (fscanf(f, "%lf", &u) != 1){
	clicon_err(OE_UNIX, errno, "Error when reading /proc/uptime");
        fclose(f);
        return -1;
    }
    fclose(f);
    *sec = (int)u;
    return 0;
}
Example #16
0
/*
 * netconf_plugin_load
 * Load allplugins you can find in CLICON_NETCONF_DIR
 */
int 
netconf_plugin_load(clicon_handle h)
{
    int            retval = -1;
    char          *dir;
    int            ndp;
    struct dirent *dp;
    int            i;
    char          *filename;
    plghndl_t     *handle;

    if ((dir = clicon_netconf_dir(h)) == NULL)
	goto quit;

    /* Get plugin objects names from plugin directory */
    if((ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG, __FUNCTION__))<0)
	goto quit;

    /* Load all plugins */
    for (i = 0; i < ndp; i++) {
	filename = chunk_sprintf(__FUNCTION__, "%s/%s", dir, dp[i].d_name);
	clicon_debug(1, "DEBUG: Loading plugin '%.*s' ...", 
		     (int)strlen(filename), filename);
	if (filename == NULL) {
	    clicon_err(OE_UNIX, errno, "chunk");
	    goto quit;
	}
	if ((handle = plugin_load (h, filename, RTLD_NOW, __FUNCTION__)) == NULL)
	    goto quit;
	if ((plugins = rechunk(plugins, (nplugins+1) * sizeof (*plugins), NULL)) == NULL) {
	    clicon_err(OE_UNIX, errno, "chunk");
	    goto quit;
	}
	plugins[nplugins++] = handle;
	unchunk (filename);
    }
    retval = 0;
quit:
    unchunk_group(__FUNCTION__);
    return retval;
}
Example #17
0
/*
 * netconf_register_callback
 * Called from plugin to register a callback for a specific netconf XML tag.
 */
int
netconf_register_callback(clicon_handle h,
			  netconf_cb_t cb,      /* Callback called */
			  void *arg,        /* Arg to send to callback */
			  char *tag)        /* Xml tag when callback is made */
{
    netconf_reg_t *nr;

    if ((nr = malloc(sizeof(netconf_reg_t))) == NULL) {
	clicon_err(OE_DB, errno, "malloc: %s", strerror(errno));
	goto catch;
    }
Example #18
0
int 
vlan_add_interface(void *handle, cvec *vars, cg_var *arg)
{
    char *dot;
    cg_var *cv;
    cg_var *ifname;
    char *str;

    if ((ifname = cvec_find_var(vars, "name")) == NULL) {
	clicon_err(OE_CFG, ENOENT, "Could not find 'name' in variable vector");
	goto catch;
    }
Example #19
0
/*! This is the callback used by cli_setlog to print log message in CLI
 * param[in]  s    UNIX socket from backend  where message should be read
 * param[in]  arg  format: txt, xml, xml2txt, xml2json
 */
static int
cli_notification_cb(int   s, 
		    void *arg)
{
    struct clicon_msg *reply = NULL;
    int                eof;
    int                retval = -1;
    cxobj             *xt = NULL;
    cxobj             *xe;
    cxobj             *x;
    enum format_enum format = (enum format_enum)arg;
    
    /* get msg (this is the reason this function is called) */
    if (clicon_msg_rcv(s, &reply, &eof) < 0)
	goto done;
    if (eof){
	clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
	close(s);
	errno = ESHUTDOWN;
	event_unreg_fd(s, cli_notification_cb);
	goto done;
    }
    if (clicon_msg_decode(reply, NULL, &xt) < 0) /* XXX pass yang_spec */
	goto done;
    if ((xe = xpath_first(xt, "//event")) != NULL){
	x = NULL;
	while ((x = xml_child_each(xe, x, -1)) != NULL) {
	    switch (format){
	    case FORMAT_XML:
		if (clicon_xml2file(stdout, x, 0, 1) < 0)
		    goto done;
		break;
	    case FORMAT_TEXT:
		if (xml2txt(stdout, x, 0) < 0)
		    goto done;
		break;
	    case FORMAT_JSON:
		if (xml2json(stdout, x, 1) < 0)
		    goto done;
		break;
	    default:
		break;
	    }
	}
    }
    retval = 0;
  done:
    if (xt)
	xml_free(xt);
    if (reply)
	free(reply);
    return retval;
}
Example #20
0
/*! Reset running and start in failsafe mode. If no failsafe then quit.
  Typically done when startup status is not OK so

failsafe      ----------------------+
                            reset    \ commit
running                       |-------+---------------> RUNNING FAILSAFE
 */
int
startup_failsafe(clicon_handle h)
{
    int   retval = -1;
    int   ret;
    char *db = "failsafe";
    cbuf *cbret = NULL;

    if ((cbret = cbuf_new()) == NULL){
	clicon_err(OE_XML, errno, "cbuf_new");
	goto done;
    }
    if ((ret = xmldb_exists(h, db)) < 0)
	goto done;
    if (ret == 0){ /* No it does not exist, fail */
	clicon_err(OE_DB, 0, "Startup failed and no Failsafe database found, exiting");
	goto done;
    }
    /* Copy original running to tmp as backup (restore if error) */
    if (xmldb_copy(h, "running", "tmp") < 0)
	goto done;
    if (startup_db_reset(h, "running") < 0)
	goto done;
    ret = candidate_commit(h, db, cbret);
    if (ret != 1)
	if (xmldb_copy(h, "tmp", "running") < 0)
	    goto done;
    if (ret < 0)
	goto done;
    if (ret == 0){
	clicon_err(OE_DB, 0, "Startup failed, Failsafe database validation failed %s", cbuf_get(cbret));
	goto done;
    }
    clicon_log(LOG_NOTICE, "Startup failed, Failsafe database loaded ");
    retval = 0;
 done:
    if (cbret)
	cbuf_free(cbret);
    return retval;
}
Example #21
0
/*
 * Load a dynamic plugin object and call it's init-function
 * Note 'file' may be destructively modified
 */
static plghndl_t 
plugin_load (clicon_handle h, char *file, int dlflags, const char *cnklbl)
{
    char *error;
    void *handle = NULL;
    plginit_t *initfn;

    dlerror();    /* Clear any existing error */
    if ((handle = dlopen (file, dlflags)) == NULL) {
        error = (char*)dlerror();
	clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
	goto quit;
    }
    /* call plugin_init() if defined */
    if ((initfn = dlsym(handle, "plugin_init")) != NULL) {
	if (initfn(h) != 0) {
	    clicon_err(OE_PLUGIN, errno, "Failed to initiate %s\n", strrchr(file,'/')?strchr(file, '/'):file);
	    goto quit;
	}
    }
quit:

    return handle;
}
Example #22
0
/*
 * from_client_commit
 * Handle an incoming commit message from a client.
 * XXX: If commit succeeds and snapshot/startup fails, we have strange state:
 *   the commit has succeeded but an error message is returned.
 */
int
from_client_commit(clicon_handle h,
		   int s, 
		   struct clicon_msg *msg, 
		   const char *label)
{
    char *candidate, *running;
    uint32_t snapshot, startup;
    int retval = -1;
    char *snapshot_0;

    if (clicon_msg_commit_decode(msg, &candidate, &running, 
				&snapshot, &startup, label) < 0)
	goto err;

    if (candidate_commit(h, candidate, running) < 0){
	clicon_debug(1, "Commit %s failed",  candidate);
	retval = 0; /* We ignore errors from commit, but maybe
		       we should fail on fatal errors? */
	goto err;
    }
    clicon_debug(1, "Commit %s",  candidate);

    if (snapshot && config_snapshot(clicon_dbspec_key(h), running, clicon_archive_dir(h)) < 0)
	goto err;

    if (startup){
	snapshot_0 = chunk_sprintf(__FUNCTION__, "%s/0", 
				   clicon_archive_dir(h));
	if (file_cp(snapshot_0, clicon_startup_config(h)) < 0){
	    clicon_err(OE_PROTO, errno, "%s: Error when creating startup", 
		    __FUNCTION__);
		goto err;
	}
    }
    retval = 0;
    if (send_msg_ok(s) < 0)
	goto done;
    goto done;
  err:
    /* XXX: more elaborate errstring? */
    if (send_msg_err(s, clicon_errno, clicon_suberrno, "%s", clicon_err_reason) < 0)
	retval = -1;
  done:
    unchunk_group(__FUNCTION__);
    return retval; /* may be zero if we ignoring errors from commit */
} /* from_client_commit */
Example #23
0
/*! Set syntax mode
 */
int
cli_set_mode(clicon_handle h, 
	      cvec         *vars, 
	      cvec         *argv)
{
    int     retval = -1;
    char   *str = NULL;

    if (cvec_len(argv) != 1){
	clicon_err(OE_PLUGIN, 0, "Requires one element to be cli mode");
	goto done;
    }
    str = cv_string_get(cvec_i(argv, 0));
    cli_set_syntax_mode(h, str);
    retval = 0;
  done:
    return retval;
}
Example #24
0
/*! Add new client, typically frontend such as cli, netconf, restconf
 * @param[in]  h        Clicon handle
 * @param[in]  addr     Address of client
 * @retval     ce       Client entry
 * @retval     NULL     Error
 */
struct client_entry *
backend_client_add(clicon_handle    h, 
		   struct sockaddr *addr)
{
    struct backend_handle *bh = handle(h);
    struct client_entry   *ce;

    if ((ce = (struct client_entry *)malloc(sizeof(*ce))) == NULL){
	clicon_err(OE_PLUGIN, errno, "malloc");
	return NULL;
    }
    memset(ce, 0, sizeof(*ce));
    ce->ce_nr = bh->bh_ce_nr++;
    memcpy(&ce->ce_addr, addr, sizeof(*addr));
    ce->ce_next = bh->bh_ce_list;
    bh->bh_ce_list = ce;
    return ce;
}
Example #25
0
File: dns.c Project: andrnils/rost
/*
 * If commit is successful the current db has been replaced by the committed 
 * candidate. We simply re-create a new NTP_CONF based on it.
 */
int
transaction_end(clicon_handle h)
{    
    FILE *out = NULL;
    
    if (dns_reload == 0)
	return 0; /* Nothing has changed */

    if ((out = fopen(RESOLV_CONF, "w")) == NULL) {
	clicon_err(OE_CFG, errno, "%s: fopen", __FUNCTION__);
	return -1;
    }
    
    lvmap_print(out, clicon_running_db(h), resolv_conf_fmts, NULL);
    fclose(out);
    
    return 0;
}
Example #26
0
/*! Unlock database
 * 
 * @param[in] h      Clicon handle
 * @param[in] cvv    Not used
 * @param[in] arg    A string with <database> 
 * @code
 * lock("comment"), cli_lock("running"); 
 * @endcode
 * XXX: format is a memory leak
 */
int
cli_unlock(clicon_handle h, 
	   cvec         *cvv, 
	   cvec         *argv)
{
    char            *db;
    int              retval = -1;

    if (cvec_len(argv) != 1){
	clicon_err(OE_PLUGIN, 0, "Requires arguments: <db>");
	goto done;
    }
    db = cv_string_get(cvec_i(argv, 0));
    if (clicon_rpc_unlock(h, db) < 0) 
	goto done;
    retval = 0;
  done:
    return retval;
}
Example #27
0
/*! Compare two dbs using XML. Write to file and run diff
 * @param[in]   h     Clicon handle
 * @param[in]   cvv  
 * @param[in]   arg   arg: 0 as xml, 1: as text
 */
int
compare_dbs(clicon_handle h, 
	    cvec         *cvv, 
	    cvec         *argv)
{
    cxobj *xc1 = NULL; /* running xml */
    cxobj *xc2 = NULL; /* candidate xml */
    cxobj *xerr;
    int    retval = -1;
    int    astext;

    if (cvec_len(argv) > 1){
	clicon_err(OE_PLUGIN, 0, "Requires 0 or 1 element. If given: astext flag 0|1");
	goto done;
    }
    if (cvec_len(argv))
	astext = cv_int32_get(cvec_i(argv, 0));
    else
	astext = 0;
    if (clicon_rpc_get_config(h, "running", "/", &xc1) < 0)
	goto done;
    if ((xerr = xpath_first(xc1, "/rpc-error")) != NULL){
	clicon_rpc_generate_error("Get configuration", xerr);
	goto done;
    }
    if (clicon_rpc_get_config(h, "candidate", "/", &xc2) < 0)
	goto done;
    if ((xerr = xpath_first(xc2, "/rpc-error")) != NULL){
	clicon_rpc_generate_error("Get configuration", xerr);
	goto done;
    }
    if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
	goto done;
    retval = 0;
  done:
    if (xc1)
	xml_free(xc1);    
    if (xc2)
	xml_free(xc2);

    return retval;
}
Example #28
0
/* 
 * Unload a plugin
 */
static int
plugin_unload(clicon_handle h, void *handle)
{
    int retval = 0;
    char *error;
    plgexit_t *exitfn;

    /* Call exit function is it exists */
    exitfn = dlsym(handle, "plugin_exit");
    if (dlerror() == NULL)
	exitfn(h);

    dlerror();    /* Clear any existing error */
    if (dlclose(handle) != 0) {
	error = (char*)dlerror();
	clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
	/* Just report */
    }
    return retval;
}
Example #29
0
/*! Load a set of plugin objects from a directory and and call their init-function
 * @param[in]  h     Clicon handle
 * @param[in]  function Which function symbol to load and call (eg CLIXON_PLUGIN_INIT)
 * @param[in]  dir   Directory. .so files in this dir will be loaded.
 * @param[in]  regexp Regexp for matching files in plugin directory. Default *.so.
 * @retval     0     OK
 * @retval     -1    Error
 */
int
clixon_plugins_load(clicon_handle h,
    		    char         *function,
		    char         *dir,
    		    char         *regexp)
{
    int            retval = -1;
    int            ndp;
    struct dirent *dp = NULL;
    int            i;
    char           filename[MAXPATHLEN];
    clixon_plugin *cp;
    int            ret;

    clicon_debug(1, "%s", __FUNCTION__); 
    /* Get plugin objects names from plugin directory */
    if((ndp = clicon_file_dirent(dir, &dp, regexp?regexp:"(.so)$", S_IFREG)) < 0)
	goto done;
    /* Load all plugins */
    for (i = 0; i < ndp; i++) {
	snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
	clicon_debug(1, "DEBUG: Loading plugin '%.*s' ...", 
		     (int)strlen(filename), filename);
	if ((ret = plugin_load_one(h, filename, function, RTLD_NOW, &cp)) < 0)
	    goto done;
	if (ret == 0)
	    continue;
	_clixon_nplugins++;
	if ((_clixon_plugins = realloc(_clixon_plugins, _clixon_nplugins*sizeof(clixon_plugin))) == NULL) {
	    clicon_err(OE_UNIX, errno, "realloc");
	    goto done;
	}
	_clixon_plugins[_clixon_nplugins-1] = *cp;
	free(cp);
    }
    retval = 0;
done:
    if (dp)
	free(dp);
    return retval;
}
Example #30
0
/*! Set debug level on backend daemon (not CLI)
 * @param[in] h     Clicon handle
 * @param[in] vars  If variable "level" exists, its integer value is used
 * @param[in] arg   Else use the integer value of argument
 * @note The level is either what is specified in arg as int argument.
 *       _or_ if a 'level' variable is present in vars use that value instead.
 */
int
cli_debug_backend(clicon_handle h, 
		  cvec         *vars, 
		  cvec         *argv)
{
    int     retval = -1;
    cg_var *cv;
    int     level;

    if ((cv = cvec_find(vars, "level")) == NULL){
	if (cvec_len(argv) != 1){
	    clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
	    goto done;
	}
	cv = cvec_i(argv, 0);
    }
    level = cv_int32_get(cv);
    /* config daemon */
    retval = clicon_rpc_debug(h, level);
 done:
    return retval;
}