sysrest: Initial add

A RESTCONF front-end for sysrepo.
This commit is contained in:
Tobias Waldekranz
2023-04-05 17:00:01 +02:00
parent e729c82c32
commit 7eec8c2964
14 changed files with 317 additions and 2 deletions
+6 -1
View File
@@ -45,8 +45,13 @@ http {
index index.html index.htm;
}
location /.well-known/host-meta {
fastcgi_pass unix:/run/sysrest.sock;
include fastcgi_params;
}
location /restconf/ {
fastcgi_pass unix:/var/run/clixon/restconf.sock;
fastcgi_pass unix:/run/sysrest.sock;
include fastcgi_params;
}
+1
View File
@@ -18,6 +18,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/python-templating/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-plugins-common/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-plugin-system/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrest/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/umgmt/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/querierd/Config.in"
+1 -1
View File
@@ -7,7 +7,7 @@
# ... except for some core services
reserved()
{
for svc in dnsmasq getty klish lldpd nginx sysklogd sysrepo; do
for svc in dnsmasq getty klish lldpd nginx sysklogd sysrepo sysrest; do
[ "$1" = "${svc}.conf" ] && return 0
done
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_SYSREST
bool "sysrest"
depends on BR2_PACKAGE_SYSREPO
select BR2_PACKAGE_LIBCFGI
help
RESTCONF front-end for Sysrepo
+1
View File
@@ -0,0 +1 @@
service if:<boot/netconf> [2345789] sysrest -- RESTCONF daemon
+20
View File
@@ -0,0 +1,20 @@
################################################################################
#
# sysrest
#
################################################################################
SYSREST_VERSION = 1.0
SYSREST_LICENSE = BSD-3-Clause
SYSREST_SITE_METHOD = local
SYSREST_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/sysrest
SYSREST_DEPENDENCIES = sysrepo libfcgi
SYSREST_AUTORECONF = YES
define SYSREST_INSTALL_EXTRA
cp $(SYSREST_PKGDIR)/sysrest.conf $(FINIT_D)/available/
ln -sf ../available/sysrest.conf $(FINIT_D)/enabled/sysrest.conf
endef
SYSREST_TARGET_FINALIZE_HOOKS += SYSREST_INSTALL_EXTRA
$(eval $(autotools-package))
+33
View File
@@ -0,0 +1,33 @@
*~
*.o
*.la
*.lo
*.so
.deps
.libs
/aclocal.m4
/autom4te.cache/
/aux
/clixon.xml
/compile
/config.h
/config.h.in
/config.guess
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4
/missing
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
+25
View File
@@ -0,0 +1,25 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of copyright holders nor the names of
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+3
View File
@@ -0,0 +1,3 @@
SUBDIRS = src
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
+15
View File
@@ -0,0 +1,15 @@
Configuration Daemon
====================
`confd` is the Infix configuration daemon that serves as the glue
between sysrepo and netopeer2 (NETCONF) and the UNIX system under
it all.
Origin & References
-------------------
Based on the Open Source [dklibc/sysrepo_plugin_ietf_system][0]
project by Denis Kalashnikov.
[0]: https://github.com/dklibc/sysrepo_plugin_ietf_system
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -vifm
+50
View File
@@ -0,0 +1,50 @@
AC_PREREQ(2.61)
AC_INIT([sysrest], [1.0.0],
[https://github.com/kernelkit/infix/issues])
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
AM_SILENT_RULES(yes)
LT_INIT
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_PROG_CC
AC_PROG_INSTALL
# Check for pkg-config first, warn if it's not installed
PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
PKG_CHECK_MODULES([fcgi], [fcgi >= 2.4.2])
# Plugin installation path for sysrepo-plugind
dnl PKG_CHECK_VAR([srpdplugindir], [sysrepo], [SRPD_PLUGINS_PATH])
dnl AC_SUBST(srpdplugindir)
dnl test "x$prefix" = xNONE && prefix=$ac_default_prefix
dnl test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
dnl DATAROOTDIR=`eval echo $datarootdir`
dnl DATAROOTDIR=`eval echo $DATAROOTDIR`
dnl AC_SUBST(DATAROOTDIR)
dnl LIBDIR=`eval echo $libdir`
dnl LIBDIR=`eval echo $LIBDIR`
dnl AC_SUBST(LIBDIR)
dnl LOCALSTATEDIR=`eval echo $localstatedir`
dnl LOCALSTATEDIR=`eval echo $LOCALSTATEDIR`
dnl AC_SUBST(LOCALSTATEDIR)
dnl RUNSTATEDIR=`eval echo $runstatedir`
dnl RUNSTATEDIR=`eval echo $RUNSTATEDIR`
dnl AC_SUBST(RUNSTATEDIR)
dnl SYSCONFDIR=`eval echo $sysconfdir`
dnl SYSCONFDIR=`eval echo $SYSCONFDIR`
dnl AC_SUBST(SYSCONFDIR)
AC_OUTPUT
+6
View File
@@ -0,0 +1,6 @@
sbin_PROGRAMS = sysrest
sysrest_SOURCES = main.c
sysrest_CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter \
$(sysrepo_CFLAGS) $(fcgi_CFLAGS)
sysrest_LDADD = $(sysrepo_LIBS) $(fcgi_LIBS)
+147
View File
@@ -0,0 +1,147 @@
#include <errno.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcgiapp.h>
static const char *rootpath = "/restconf/";
static void dumpenv(char **envp)
{
fprintf(stderr, "ENV:\n");
for (; *envp; envp++) {
fprintf(stderr, " %s\n", *envp);
}
}
int serve_host_meta(FCGX_Request *req)
{
const char *method;
size_t len;
char *buf;
FILE *fp;
method = FCGX_GetParam("REQUEST_METHOD", req->envp);
if (!method || (strcmp(method, "GET") && strcmp(method, "HEAD")))
return -EINVAL;
fp = open_memstream(&buf, &len);
if (!fp)
return -ENOMEM;
fprintf(fp,
"<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>"
"<Link rel='restconf' href='%s'/>"
"</XRD>", rootpath);
fclose(fp);
FCGX_FPrintF(req->out, "Content-Type: application/xrd+xml\r\n");
FCGX_FPrintF(req->out, "Content-Length: %zd\r\n", len);
FCGX_FPrintF(req->out, "Connection: close\r\n");
FCGX_PutS("\r\n", req->out);
if (!strcmp(method, "GET"))
FCGX_PutStr(buf, len, req->out);
free(buf);
FCGX_Finish_r(req);
return 0;
}
int serve_restconf(FCGX_Request *req)
{
FCGX_FPrintF(req->out, "Content-type: text/html\r\n\r\n");
FCGX_FPrintF(req->out, "RESTCONF\r\n");
FCGX_Finish_r(req);
return 0;
}
int serve(int sd)
{
FCGX_Request req;
const char *uri;
int err = 0;
for (FCGX_InitRequest(&req, sd, 0);
FCGX_Accept_r(&req) == 0;
FCGX_InitRequest(&req, sd, 0)) {
dumpenv(req.envp);
uri = FCGX_GetParam("REQUEST_URI", req.envp);
if (!uri)
continue;
if (!strcmp(uri, "/.well-known/host-meta"))
err = serve_host_meta(&req);
else if (!strncmp(uri, rootpath, strlen(rootpath)))
err = serve_restconf(&req);
else
err = -EINVAL;
if (err) {
FCGX_FPrintF(req.out, "Status: 400 Bad Request\r\n");
FCGX_FPrintF(req.out, "Content-Type: text/html\r\n");
FCGX_FPrintF(req.out, "Connection: close\r\n");
FCGX_PutS("\r\n", req.out);
FCGX_Finish_r(&req);
break;
}
}
FCGX_Free(&req, sd);
if (err)
fprintf(stderr, "Unable to handle request: %d\n", err);
return err ? 1 : 0;
}
int setup_sock(const char *sockpath, const char *groupname)
{
struct group *g;
int sd;
sd = FCGX_OpenSocket(sockpath, 10);
if (sd < 0) {
perror("Unable to create socket");
return -1;
}
g = getgrnam(groupname);
if (!g)
return -1;
if (chown(sockpath, -1, g->gr_gid)) {
perror("Unable to set socket group");
return -1;
}
if (chmod(sockpath, S_IRWXU|S_IRWXG|S_IROTH) < 0){
perror("Unable to set socket permissions");
return -1;
}
return sd;
}
int main(int argc, char **argv, char **envp)
{
int sd;
if (FCGX_Init()) {
perror("Unable to initialize libfcgi");
return 1;
}
sd = setup_sock("/run/sysrest.sock", "www-data");
if (sd < 0)
return 1;
return serve(sd);
}