* Experimental IPC API, clixon_client, to support a loose integration model
* Many systems using other tools employ such a model, and this API is an effort to make a usage of clixon easier * see https://clixon-docs.readthedocs.io/en/latest/overview.html#loose-integration * This is work-in-progress and is expected to change
This commit is contained in:
parent
2a392ca0e9
commit
c269d094e4
5 changed files with 548 additions and 1 deletions
|
|
@ -29,6 +29,8 @@
|
||||||
## 4.10.0
|
## 4.10.0
|
||||||
Expected: February 2021
|
Expected: February 2021
|
||||||
|
|
||||||
|
### New features
|
||||||
|
|
||||||
### C/CLI-API changes on existing features
|
### C/CLI-API changes on existing features
|
||||||
|
|
||||||
Developers may need to change their code
|
Developers may need to change their code
|
||||||
|
|
@ -51,6 +53,10 @@ Users may have to change how they access the system
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
|
||||||
|
* Experimental IPC API, `clixon_client`, to support a loose integration model
|
||||||
|
* Many systems using other tools employ such a model, and this API is an effort to make a usage of clixon easier
|
||||||
|
* see https://clixon-docs.readthedocs.io/en/latest/overview.html#loose-integration
|
||||||
|
* This is work-in-progress and is expected to change
|
||||||
* Use [https://github.com/clicon/libevhtp](https://github.com/clicon/libevhtp) instead of [https://github.com/criticalstack/libevhtp](https://github.com/criticalstack/libevhtp) as a source of the evhtp source
|
* Use [https://github.com/clicon/libevhtp](https://github.com/clicon/libevhtp) instead of [https://github.com/criticalstack/libevhtp](https://github.com/criticalstack/libevhtp) as a source of the evhtp source
|
||||||
* Added callback to process-control RPC feature in clixon-lib.yang to manage processes
|
* Added callback to process-control RPC feature in clixon-lib.yang to manage processes
|
||||||
* WHen an RPC comes in, be able to look at configuration
|
* WHen an RPC comes in, be able to look at configuration
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ extern "C" {
|
||||||
#include <clixon/clixon_xml_changelog.h>
|
#include <clixon/clixon_xml_changelog.h>
|
||||||
#include <clixon/clixon_xml_nsctx.h>
|
#include <clixon/clixon_xml_nsctx.h>
|
||||||
#include <clixon/clixon_xml_vec.h>
|
#include <clixon/clixon_xml_vec.h>
|
||||||
|
#include <clixon/clixon_client.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables generated by Makefile
|
* Global variables generated by Makefile
|
||||||
|
|
|
||||||
70
lib/clixon/clixon_client.h
Normal file
70
lib/clixon/clixon_client.h
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
|
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the "GPL"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2, indicate
|
||||||
|
your decision by deleting the provisions above and replace them with the
|
||||||
|
notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLIXON_CLIENT_H
|
||||||
|
#define _CLIXON_CLIENT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prototypes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int clixon_client_connect(void *h, const struct sockaddr* srv, int srv_sz);
|
||||||
|
int clixon_client_close(int sock);
|
||||||
|
int clixon_client_session_start(void *h, const char *db);
|
||||||
|
int clixon_client_session_end(void *h);
|
||||||
|
int clixon_client_subscribe(int sock, int priority, int nspace,
|
||||||
|
int *spoint, const char *fmt, ...);
|
||||||
|
int clixon_client_subscribe_done(int sock);
|
||||||
|
int clixon_client_read_subscription_socket(int sock, int sub_points[], int *resultlen);
|
||||||
|
int clixon_client_num_instances(int sock, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_bool(int sock, int *rval, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_str(int sock, char *rval, int n, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_u_int8(int sock, uint8_t *rval, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_u_int16(int sock, uint16_t *rval, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_u_int32(int sock, uint32_t *rval, const char *xnamespace, const char *xpath);
|
||||||
|
int clixon_client_get_u_int64(int sock, uint64_t *rval, const char *xnamespace, const char *xpath);
|
||||||
|
|
||||||
|
void *clixon_client_init(const char *name, FILE *estream, const int debug, const char *config_file);
|
||||||
|
int clixon_client_terminate(void *h);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CLIXON_CLIENT_H */
|
||||||
|
|
@ -83,7 +83,7 @@ SRC = clixon_sig.c clixon_uid.c clixon_log.c clixon_err.c clixon_event.c \
|
||||||
clixon_proto.c clixon_proto_client.c \
|
clixon_proto.c clixon_proto_client.c \
|
||||||
clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_xpath_function.c clixon_xpath_optimize.c \
|
clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_xpath_function.c clixon_xpath_optimize.c \
|
||||||
clixon_sha1.c clixon_datastore.c clixon_datastore_write.c clixon_datastore_read.c \
|
clixon_sha1.c clixon_datastore.c clixon_datastore_write.c clixon_datastore_read.c \
|
||||||
clixon_netconf_lib.c clixon_stream.c clixon_nacm.c
|
clixon_netconf_lib.c clixon_stream.c clixon_nacm.c clixon_client.c
|
||||||
|
|
||||||
YACCOBJS = lex.clixon_xml_parse.o clixon_xml_parse.tab.o \
|
YACCOBJS = lex.clixon_xml_parse.o clixon_xml_parse.tab.o \
|
||||||
lex.clixon_yang_parse.o clixon_yang_parse.tab.o \
|
lex.clixon_yang_parse.o clixon_yang_parse.tab.o \
|
||||||
|
|
|
||||||
470
lib/src/clixon_client.c
Normal file
470
lib/src/clixon_client.c
Normal file
|
|
@ -0,0 +1,470 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright (C) 2009-2019 Olof Hagsand
|
||||||
|
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
|
||||||
|
|
||||||
|
This file is part of CLIXON.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Alternatively, the contents of this file may be used under the terms of
|
||||||
|
the GNU General Public License Version 3 or later (the "GPL"),
|
||||||
|
in which case the provisions of the GPL are applicable instead
|
||||||
|
of those above. If you wish to allow use of your version of this file only
|
||||||
|
under the terms of the GPL, and not to allow others to
|
||||||
|
use your version of this file under the terms of Apache License version 2, indicate
|
||||||
|
your decision by deleting the provisions above and replace them with the
|
||||||
|
notice and other provisions required by the GPL. If you do not delete
|
||||||
|
the provisions above, a recipient may use your version of this file under
|
||||||
|
the terms of any one of the Apache License version 2 or the GPL.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "clixon_config.h" /* generated by config & autoconf */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
/* cligen */
|
||||||
|
#include <cligen/cligen.h>
|
||||||
|
|
||||||
|
#include "clixon_queue.h"
|
||||||
|
#include "clixon_string.h"
|
||||||
|
#include "clixon_hash.h"
|
||||||
|
#include "clixon_handle.h"
|
||||||
|
#include "clixon_log.h"
|
||||||
|
#include "clixon_err.h"
|
||||||
|
#include "clixon_yang.h"
|
||||||
|
#include "clixon_options.h"
|
||||||
|
#include "clixon_xml.h"
|
||||||
|
#include "clixon_xml_nsctx.h"
|
||||||
|
#include "clixon_xml_io.h"
|
||||||
|
#include "clixon_xpath_ctx.h"
|
||||||
|
#include "clixon_xpath.h"
|
||||||
|
#include "clixon_netconf_lib.h"
|
||||||
|
#include "clixon_proto.h"
|
||||||
|
#include "clixon_proto_client.h"
|
||||||
|
#include "clixon_client.h"
|
||||||
|
|
||||||
|
/*! Initialize Clixon client API
|
||||||
|
* @param[in] name Name of client (NYI)
|
||||||
|
* @param[in] estream Error/debug file (NULL: syslog)
|
||||||
|
* @param[in] debug Clixon debug flag
|
||||||
|
* @param[in] config_file Clixon configuration file (eg for CLICON_SOCK)
|
||||||
|
* @see clixon_client_close
|
||||||
|
*/
|
||||||
|
clicon_handle
|
||||||
|
clixon_client_init(const char *name,
|
||||||
|
FILE *estream,
|
||||||
|
const int debug,
|
||||||
|
const char *config_file)
|
||||||
|
{
|
||||||
|
clicon_handle h;
|
||||||
|
|
||||||
|
clicon_log_init("clixon", LOG_DEBUG, CLICON_LOG_STDERR);
|
||||||
|
clicon_debug_init(debug, estream);
|
||||||
|
fprintf(stderr, "fprintf %s\n", __FUNCTION__);
|
||||||
|
/* Initiate CLICON handle. CLIgen is also initialized */
|
||||||
|
if ((h = clicon_handle_init()) == NULL)
|
||||||
|
return NULL;
|
||||||
|
/* Set clixon config file - reuse the one in the main installation */
|
||||||
|
clicon_option_str_set(h, "CLICON_CONFIGFILE", (char*)config_file);
|
||||||
|
/* Find, read and parse configfile */
|
||||||
|
if (clicon_options_main(h) < 0)
|
||||||
|
return NULL;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Deallocate everything from client_init
|
||||||
|
* @see clixon_client_init
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_client_terminate(clicon_handle h)
|
||||||
|
{
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
clicon_handle_exit(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Connect client to clixon backend according to config and return a socket
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @retval s Socket, need to be closed by caller
|
||||||
|
* @see clixon_client_close Close the socket returned here
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_client_connect(clicon_handle h,
|
||||||
|
const struct sockaddr* srv,
|
||||||
|
int srv_sz)
|
||||||
|
{
|
||||||
|
int s = -1;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clicon_rpc_connect(h, &s) < 0)
|
||||||
|
return -1;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Connect client to clixon backend according to config and return a socket
|
||||||
|
* @param[in] s Socket, opened by connect call
|
||||||
|
* @see clixon_client_connect
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_client_close(int s)
|
||||||
|
{
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
close(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_subscribe(int sock,
|
||||||
|
int priority,
|
||||||
|
int nspace,
|
||||||
|
int *spoint,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_subscribe_done(int sock)
|
||||||
|
{
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_read_subscription_socket(int sock,
|
||||||
|
int sub_points[],
|
||||||
|
int *resultlen)
|
||||||
|
{
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Internal function to construct a get-config and query a value from the backend
|
||||||
|
*
|
||||||
|
* @param[in] sock Stream socket
|
||||||
|
* @param[in] xpath XPath
|
||||||
|
* @param[in] namespace Default namespace used for non-prefixed entries in xpath. (Alt use nsc)
|
||||||
|
* @param[out] val String value
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
clixon_client_get_xdata(int sock,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath,
|
||||||
|
cxobj **xdata)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *retdata = NULL;
|
||||||
|
cxobj *xret = NULL;
|
||||||
|
cxobj *xd;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
struct clicon_msg *msg = NULL;
|
||||||
|
const char *db = "running";
|
||||||
|
cvec *nsc = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) == NULL)
|
||||||
|
goto done;
|
||||||
|
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
|
||||||
|
cprintf(cb, " xmlns:%s=\"%s\"",
|
||||||
|
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
|
cprintf(cb, "><get-config><source><%s/></source>", db);
|
||||||
|
if (xpath && strlen(xpath)){
|
||||||
|
cprintf(cb, "<%s:filter %s:type=\"xpath\" xmlns=\"%s\" %s:select=\"%s\"",
|
||||||
|
NETCONF_BASE_PREFIX,
|
||||||
|
NETCONF_BASE_PREFIX,
|
||||||
|
namespace,
|
||||||
|
NETCONF_BASE_PREFIX,
|
||||||
|
xpath);
|
||||||
|
if (xml_nsctx_cbuf(cb, nsc) < 0)
|
||||||
|
goto done;
|
||||||
|
cprintf(cb, "/>");
|
||||||
|
}
|
||||||
|
cprintf(cb, "</get-config></rpc>");
|
||||||
|
clicon_debug(1, "%s xml:%s", __FUNCTION__, cbuf_get(cb));
|
||||||
|
if ((msg = clicon_msg_encode(0, "%s", cbuf_get(cb))) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (clicon_rpc(sock, msg, &retdata) < 0)
|
||||||
|
goto done;
|
||||||
|
if (clixon_xml_parse_string(retdata, YB_NONE, NULL, &xret, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((xd = xpath_first(xret, NULL, "/rpc-reply/rpc-error")) != NULL){
|
||||||
|
xd = xml_parent(xd); /* point to rpc-reply */
|
||||||
|
clixon_netconf_error(xd, "Get config", NULL);
|
||||||
|
goto done; /* Not fatal */
|
||||||
|
}
|
||||||
|
else if ((xd = xpath_first(xret, NULL, "/rpc-reply/data")) == NULL){
|
||||||
|
if ((xd = xml_new("data", NULL, CX_ELMNT)) == NULL)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (xml_rm(xd) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*xdata = xd;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (xret)
|
||||||
|
xml_free(xret);
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
if (msg)
|
||||||
|
free(msg);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
clixon_client_get_val(int sock,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath,
|
||||||
|
char **val)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xdata = NULL;
|
||||||
|
cxobj *xobj;
|
||||||
|
|
||||||
|
if (val == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "Expected val");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#if 1 /* XXX: Problem is xpath with indexes used in original need to change to [0] in the 2nd access */
|
||||||
|
if (clixon_client_get_xdata(sock, namespace, "/", &xdata) < 0)
|
||||||
|
goto done;
|
||||||
|
#else
|
||||||
|
if (clixon_client_get_xdata(sock, namespace, xpath, &xdata) < 0)
|
||||||
|
goto done;
|
||||||
|
#endif
|
||||||
|
if ((xobj = xpath_first(xdata, NULL, "%s", xpath)) == NULL){
|
||||||
|
clicon_err(OE_XML, ENOENT, "Expected local xpath result");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*val = xml_body(xobj);
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Get number of list entries
|
||||||
|
* @param[in] sock Stream socket
|
||||||
|
* @note there is no way using netconf to get this number: instead the whole list is retrieved.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_client_num_instances(int sock,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xdata = NULL;
|
||||||
|
cxobj **vec = NULL;
|
||||||
|
size_t veclen;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
#if 1 /* XXX: Problem is xpath with indexes used in original need to change to [0] in the 2nd access */
|
||||||
|
if (clixon_client_get_xdata(sock, namespace, "/", &xdata) < 0)
|
||||||
|
goto done;
|
||||||
|
#else
|
||||||
|
if (clixon_client_get_xdata(sock, namespace, xpath, &xdata) < 0)
|
||||||
|
goto done;
|
||||||
|
#endif
|
||||||
|
if (xpath_vec(xdata, NULL, "%s", &vec, &veclen, xpath) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = veclen;
|
||||||
|
done:
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_get_bool(int sock,
|
||||||
|
int *rval,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
uint8_t val0=0;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = parse_bool(val, &val0, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_bool");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "%s", reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
*rval = (int)val0;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Get string using get-config
|
||||||
|
* @param[in] sock Stream socket
|
||||||
|
* @param[out] rval Return value string
|
||||||
|
* @param[in] n Length of string
|
||||||
|
* @param[in] xpath XPath
|
||||||
|
* @param[in] namespace Default namespace used for non-prefixed entries in xpath. (Alt use nsc)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_client_get_str(int sock,
|
||||||
|
char *rval,
|
||||||
|
int n,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
strncpy(rval, val, n-1);
|
||||||
|
rval[n-1]= '\0';
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_get_u_int8(int sock,
|
||||||
|
uint8_t *rval,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = parse_uint8(val, rval, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_bool");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "%s", reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_get_u_int16(int sock,
|
||||||
|
uint16_t *rval,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = parse_uint16(val, rval, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_bool");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "%s", reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_get_u_int32(int sock,
|
||||||
|
uint32_t *rval,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = parse_uint32(val, rval, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_bool");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "%s", reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
clixon_client_get_u_int64(int sock,
|
||||||
|
uint64_t *rval,
|
||||||
|
const char *namespace,
|
||||||
|
const char *xpath)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *val = NULL;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
|
if (clixon_client_get_val(sock, namespace, xpath, &val) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ret = parse_uint64(val, rval, &reason)) < 0){
|
||||||
|
clicon_err(OE_XML, errno, "parse_bool");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){
|
||||||
|
clicon_err(OE_XML, EINVAL, "%s", reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue