experimental restconf

This commit is contained in:
Olof hagsand 2016-05-20 18:33:48 +02:00
parent dfa30aa39c
commit 0356b2225f
13 changed files with 2886 additions and 62 deletions

View file

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

View file

@ -284,11 +284,14 @@ terminate(clicon_handle h)
}
/*
* usage
/*! Usage help routine
* @param[in] h Clicon handle
* @param[in] argv0 command line
*/
static void
usage(char *argv0, clicon_handle h)
usage(clicon_handle h,
char *argv0,
{
char *netconfdir = clicon_netconf_dir(h);
@ -328,14 +331,14 @@ main(int argc, char **argv)
while ((c = getopt(argc, argv, NETCONF_OPTS)) != -1)
switch (c) {
case 'h' : /* help */
usage(argv[0], h);
usage(h, argv[0]);
break;
case 'D' : /* debug */
debug = 1;
break;
case 'f': /* override config file */
if (!strlen(optarg))
usage(argv[0], h);
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg);
break;
case 'S': /* Log on syslog */
@ -369,11 +372,11 @@ main(int argc, char **argv)
break;
case 'd': /* Plugin directory */
if (!strlen(optarg))
usage(argv[0], h);
usage(h, argv[0]);
clicon_option_str_set(h, "CLICON_NETCONF_DIR", optarg);
break;
default:
usage(argv[0], h);
usage(h, argv[0]);
break;
}
argc -= optind;

96
apps/restconf/Makefile.in Normal file
View file

@ -0,0 +1,96 @@
#
# 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/>.
#
VPATH = @srcdir@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
CC = @CC@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
wwwdir = /www-data
libexecdir = @libexecdir@
localstatedir = @localstatedir@
sysconfdir = @sysconfdir@
SH_SUFFIX = @SH_SUFFIX@
CLIXON_MAJOR = @CLIXON_VERSION_MAJOR@
CLIXON_MINOR = @CLIXON_VERSION_MINOR@
# Use this clixon lib for linking
CLIXON_LIB = libclixon.so.$(CLIXON_MAJOR).$(CLIXON_MINOR)
# For dependency
LIBDEPS = $(top_srcdir)/lib/src/$(CLIXON_LIB)
LIBS = -L$(top_srcdir)/lib/src @LIBS@ -l:$(CLIXON_LIB)
CPPFLAGS = @CPPFLAGS@
INCLUDES = -I. -I$(top_srcdir)/lib/src -I$(top_srcdir)/lib -I$(top_srcdir)/include -I$(top_srcdir) @INCLUDES@
SRC = restconf_lib.c
OBJS = $(SRC:.c=.o)
APPSRC = restconf_main.c
APPOBJ = $(APPSRC:.c=.o)
APPL = clixon_restconf
all: $(APPL)
clean:
rm -f $(OBJS) *.core $(APPL) $(APPOBJ)
distclean: clean
rm -f Makefile *~ .depend
# Put demon in bin
# Put other executables in libexec/
# Also create a libexec/ directory for writeable/temporary files.
# Put config file in etc/
install: $(APPL)
install -d $(DESTDIR)$(wwwdir)
install $(APPL) $(DESTDIR)$(wwwdir)
install-include:
uninstall:
rm -f $(wwwdir)/$(APPL)
.SUFFIXES:
.SUFFIXES: .c .o
.c.o:
$(CC) $(INCLUDES) -D__PROGRAM__=\"$(APPL)\" $(CPPFLAGS) $(CFLAGS) -c $<
$(APPL) : $(APPOBJ) $(OBJS) $(LIBDEPS)
$(CC) $(LDFLAGS) $(APPOBJ) $(OBJS) $(LIBS) -o $@
TAGS:
find . -name '*.[chyl]' -print | etags -
depend:
$(CC) $(DEPENDFLAGS) @DEFS@ $(INCLUDES) $(CFLAGS) -MM $(SRC) $(APPSRC) > .depend
#include .depend

32
apps/restconf/README Normal file
View file

@ -0,0 +1,32 @@
Work-in-progress restconf server
See draft-ietf-netconf-restconf-13.txt
Example nginx-default file:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
index index.html index.htm;
# Make site accessible from http://localhost/
server_name localhost;
location / {
root /usr/share/nginx/html;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
# pass the REST API to FastCGI server
location /restconf {
root /usr/share/nginx/html/restconf;
fastcgi_pass unix:/www-data/fastcgi_api.sock;
include fastcgi_params;
}
}

1133
apps/restconf/restconf_lib.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/*
*
* $COPYRIGHTSTATEMENT$
*
* $LICENSE$
* This is backend headend sender code, ie communication with a pmagent
*/
#ifndef _RESTCONF_LIB_H_
#define _RESTCONF_LIB_H_
/*
* Constants
*/
#define USER_COOKIE "c-user" /* connected user cookie */
#define WWW_USER "root"
#define WWW_PASSWD "9rundpaj" // XXX
#define DEFAULT_TEMPLATE "nordunet" /* XXX Default sender template must be in conf */
#define CONFIG_FILE "/usr/local/etc/grideye.conf"
#define NETCONF_BIN "/usr/local/bin/clixon_netconf"
#define NETCONF_OPTS "-qS"
/*
* Prototypes
*/
int notfound(FCGX_Request *r);
char *ival2influxdb(char *ival);
int openfile(FCGX_Request *r, char *dir, char *filename);
int errorfn(FCGX_Request *r, char *root, char *reason);
int str2cvec(char *string, char delim1, char delim2, cvec **cvp);
int netconf_rpc(cbuf *result, char *format, ...);
int netconf_cmd(FCGX_Request *r, char *data);
int cli_rpc(cbuf *result, char *mode, char *format, ...);
int cli_cmd(FCGX_Request *r, char *mode, char *cmd);
int check_credentials(char *passwd, cxobj *cx);
int get_db_entry(char *entry, char *attr, char *val, cxobj **cx);
int get_user_cookie(char *cookiestr, char *attribute, char **val);
int test(FCGX_Request *r, int dbg);
cbuf *readdata(FCGX_Request *r);
int create_database(char *server_addr, char *database, char *www_user, char *www_passwd);
int create_db_user(char *server_addr, char *database, char *user, char *password, char *www_user, char *www_passwd);
int url_post(char *url, char *username, char *passwd, char *putdata,
char *expect, char **getdata);
int b64_decode(const char *b64_buf, char *buf, size_t buf_len);
int metric_spec_description(char *metric, char **result);
int metric_spec_units(char *metric, char **result);
#endif /* _RESTCONF_LIB_H_ */

File diff suppressed because it is too large Load diff

View file

@ -118,5 +118,8 @@ CLICON_XMLDB_DIR localstatedir/APPNAME
# Dont include keys in cvec in cli vars callbacks, ie a & k in 'a <b> k <c>' ignored
# CLICON_CLI_VARONLY 1
# FastCGI unix socket. Should be specified in webserver
# Eg in nginx: fastcgi_pass unix:/www-data/clicon_restconf.sock;
CLICON_RESTCONF_PATH "/www-data/clicon_restconf.sock"

101
configure vendored
View file

@ -4155,6 +4155,55 @@ _ACEOF
fi
# restconf uses libcurl (I think?)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init in -lcurl" >&5
$as_echo_n "checking for curl_global_init in -lcurl... " >&6; }
if ${ac_cv_lib_curl_curl_global_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcurl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char curl_global_init ();
int
main ()
{
return curl_global_init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_curl_curl_global_init=yes
else
ac_cv_lib_curl_curl_global_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_global_init" >&5
$as_echo "$ac_cv_lib_curl_curl_global_init" >&6; }
if test "x$ac_cv_lib_curl_curl_global_init" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCURL 1
_ACEOF
LIBS="-lcurl $LIBS"
else
as_fn_error $? "libcurl missing" "$LINENO" 5
fi
for ac_func in inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@ -4168,6 +4217,55 @@ fi
done
# Lives in libfcgi-dev
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FCGX_Init in -lfcgi" >&5
$as_echo_n "checking for FCGX_Init in -lfcgi... " >&6; }
if ${ac_cv_lib_fcgi_FCGX_Init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lfcgi $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char FCGX_Init ();
int
main ()
{
return FCGX_Init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_fcgi_FCGX_Init=yes
else
ac_cv_lib_fcgi_FCGX_Init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fcgi_FCGX_Init" >&5
$as_echo "$ac_cv_lib_fcgi_FCGX_Init" >&6; }
if test "x$ac_cv_lib_fcgi_FCGX_Init" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBFCGI 1
_ACEOF
LIBS="-lfcgi $LIBS"
else
as_fn_error $? "libfcgi-dev missing" "$LINENO" 5
fi
# Check if extra keys inserted for database lists containing content. Eg A.n.foo = 3
# means A.3 $!a=foo exists
@ -4193,7 +4291,7 @@ fi
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/dbctrl/Makefile apps/xmldb/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/docker/Makefile docker/Makefile docker/cli/Makefile docker/cli/Dockerfile docker/backend/Makefile docker/backend/Dockerfile docker/netconf/Makefile docker/netconf/Dockerfile doc/Makefile"
ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile apps/dbctrl/Makefile apps/xmldb/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/docker/Makefile docker/Makefile docker/cli/Makefile docker/cli/Dockerfile docker/backend/Makefile docker/backend/Dockerfile docker/netconf/Makefile docker/netconf/Dockerfile doc/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -4894,6 +4992,7 @@ do
"apps/cli/Makefile") CONFIG_FILES="$CONFIG_FILES apps/cli/Makefile" ;;
"apps/backend/Makefile") CONFIG_FILES="$CONFIG_FILES apps/backend/Makefile" ;;
"apps/netconf/Makefile") CONFIG_FILES="$CONFIG_FILES apps/netconf/Makefile" ;;
"apps/restconf/Makefile") CONFIG_FILES="$CONFIG_FILES apps/restconf/Makefile" ;;
"apps/dbctrl/Makefile") CONFIG_FILES="$CONFIG_FILES apps/dbctrl/Makefile" ;;
"apps/xmldb/Makefile") CONFIG_FILES="$CONFIG_FILES apps/xmldb/Makefile" ;;
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;

View file

@ -132,8 +132,14 @@ AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(nsl, xdr_char)
AC_CHECK_LIB(dl, dlopen)
# restconf uses libcurl (I think?)
AC_CHECK_LIB(curl, curl_global_init,, AC_MSG_ERROR([libcurl missing]))
AC_CHECK_FUNCS(inet_aton sigaction sigvec strlcpy strsep strndup alphasort versionsort strverscmp)
# Lives in libfcgi-dev
AC_CHECK_LIB(fcgi, FCGX_Init,, AC_MSG_ERROR([libfcgi-dev missing]))
# Check if extra keys inserted for database lists containing content. Eg A.n.foo = 3
# means A.3 $!a=foo exists
@ -162,6 +168,7 @@ AC_OUTPUT(Makefile
apps/cli/Makefile
apps/backend/Makefile
apps/netconf/Makefile
apps/restconf/Makefile
apps/dbctrl/Makefile
apps/xmldb/Makefile
include/Makefile

View file

@ -40,6 +40,9 @@
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `fcgi' library (-lfcgi). */
#undef HAVE_LIBFCGI
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM

View file

@ -82,8 +82,7 @@
#define HASH_SIZE 1031 /* Number of hash buckets. Should be a prime */
/*
* A very simplistic algorithm to calculate a hash bucket index
/*! A very simplistic algorithm to calculate a hash bucket index
*/
static uint32_t
hash_bucket(const char *str)
@ -96,12 +95,9 @@ hash_bucket(const char *str)
return n % HASH_SIZE;
}
/*
* Initialize hash table.
/*! Initialize hash table.
*
* Arguments: none
*
* Returns: new pointer to hash table.
* @retval Pointer to new hash table.
*/
clicon_hash_t *
hash_init (void)
@ -116,16 +112,13 @@ hash_init (void)
return hash;
}
/*
* Free hash table.
/*! Free hash table.
*
* Arguments:
* hash - Hash table
*
* Returns: void
* @param[in] hash Hash table
* @retval void
*/
void
hash_free (clicon_hash_t *hash)
hash_free(clicon_hash_t *hash)
{
int i;
clicon_hash_t tmp;
@ -142,15 +135,16 @@ hash_free (clicon_hash_t *hash)
}
/*
* Find keys.
/*! Find hash key.
*
* key - Variable name
*
* Returns: variable structure on success, NULL on failure
* @param[in] hash Hash table
* @param[in] key Variable name
* @retval variable Hash variable structure on success
* @retval NULL Error
*/
clicon_hash_t
hash_lookup (clicon_hash_t *hash, const char *key)
hash_lookup(clicon_hash_t *hash,
const char *key)
{
uint32_t bkt;
clicon_hash_t h;
@ -164,15 +158,20 @@ hash_lookup (clicon_hash_t *hash, const char *key)
h = NEXTQ(clicon_hash_t, h);
} while (h != hash[bkt]);
}
return NULL;
}
/*
* Get value of hash
/*! Get value of hash
* @param[in] hash Hash table
* @param[in] key Variable name
* @param[out] vlen Length of value (as returned by function)
* @retval value Hash value, length given in vlen
* @retval NULL Error
*/
void *
hash_value(clicon_hash_t *hash, const char *key, size_t *vlen)
hash_value(clicon_hash_t *hash,
const char *key,
size_t *vlen)
{
clicon_hash_t h;
@ -185,19 +184,20 @@ hash_value(clicon_hash_t *hash, const char *key, size_t *vlen)
return h->h_val;
}
/*
* Copy value and add hash entry.
/*! Copy value and add hash entry.
*
* Arguments:
* hash - Hash structure
* key - New variable name
* val - New variable value
*
* Returns: new variable on success, NULL on failure
* @param[in] hash Hash table
* @param[in] key New variable name
* @param[in] val New variable value
* @param[in] vlen Length of variable value
* @retval variable New hash structure on success
* @retval NULL Failure
*/
clicon_hash_t
hash_add (clicon_hash_t *hash, const char *key, void *val, size_t vlen)
hash_add(clicon_hash_t *hash,
const char *key,
void *val,
size_t vlen)
{
void *newval;
clicon_hash_t h, new = NULL;
@ -250,17 +250,17 @@ catch:
return NULL;
}
/*
* Delete entry.
/*! Delete hash entry.
*
* Arguments:
* hash - Hash structure
* key - Variable name
* @param[in] hash Hash table
* @param[in] key Variable name
*
* Returns: 0 on success, -1 on failure
* @retval 0 success
* @retval -1 failure
*/
int
hash_del (clicon_hash_t *hash, const char *key)
hash_del(clicon_hash_t *hash,
const char *key)
{
clicon_hash_t h;
@ -277,8 +277,16 @@ hash_del (clicon_hash_t *hash, const char *key)
return 0;
}
/*! Return vector of keys in has table
*
* @param[in] hash Hash table
* @param[out] nkeys Size of key vector
* @retval vector Vector of keys
* @retval NULL Error
*/
char **
hash_keys(clicon_hash_t *hash, size_t *nkeys)
hash_keys(clicon_hash_t *hash,
size_t *nkeys)
{
int bkt;
clicon_hash_t h;
@ -311,17 +319,15 @@ catch:
return NULL;
}
/*
* Dump contents of hash to FILE pointer.
/*! Dump contents of hash to FILE pointer.
*
* Arguments:
* f - FILE pointer for print output
* hash - Hash structure
*
* Returns: void
* @param[in] hash Hash structure
* @param[in] f FILE pointer for print output
* @retval void
*/
void
hash_dump(clicon_hash_t *hash, FILE *f)
hash_dump(clicon_hash_t *hash,
FILE *f)
{
int i;
char **keys;

View file

@ -296,11 +296,12 @@ clicon_option_exists(clicon_handle h, const char *name)
* @retval NULL If option not found, or value of option is NULL
* @retval string value of option if found
* clicon options should be strings.
* To differentiate the two reasons why NULL may be returned, use function
* @note To differentiate the two reasons why NULL may be returned, use function
* clicon_option_exists() before the call
*/
char *
clicon_option_str(clicon_handle h, const char *name)
clicon_option_str(clicon_handle h,
const char *name)
{
clicon_hash_t *copt = clicon_options(h);
@ -310,9 +311,14 @@ clicon_option_str(clicon_handle h, const char *name)
}
/*! Set a single string option via handle
* @param[in] h clicon_handle
* @param[in] name option name
* @param[in] val option value, must be null-terminated string
*/
int
clicon_option_str_set(clicon_handle h, const char *name, char *val)
clicon_option_str_set(clicon_handle h,
const char *name,
char *val)
{
clicon_hash_t *copt = clicon_options(h);