mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
[TEMP] save
This commit is contained in:
@@ -17,8 +17,9 @@ 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])
|
||||
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
|
||||
PKG_CHECK_MODULES([libyang], [libyang >= 2.1.55])
|
||||
|
||||
# Plugin installation path for sysrepo-plugind
|
||||
dnl PKG_CHECK_VAR([srpdplugindir], [sysrepo], [SRPD_PLUGINS_PATH])
|
||||
|
||||
@@ -2,5 +2,5 @@ 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)
|
||||
$(libyang_CFLAGS) $(sysrepo_CFLAGS) $(fcgi_CFLAGS)
|
||||
sysrest_LDADD = $(libyang_LIBS) $(sysrepo_LIBS) $(fcgi_LIBS)
|
||||
|
||||
+290
-33
@@ -9,8 +9,120 @@
|
||||
|
||||
#include <fcgiapp.h>
|
||||
|
||||
#include <libyang/libyang.h>
|
||||
#include <libyang/plugins_exts.h>
|
||||
|
||||
#include <sysrepo.h>
|
||||
#include <sysrepo_types.h>
|
||||
|
||||
static const char *rootpath = "/restconf/";
|
||||
|
||||
enum http_method {
|
||||
HTTP_GET,
|
||||
HTTP_HEAD,
|
||||
HTTP_PATCH,
|
||||
HTTP_POST,
|
||||
HTTP_PUT,
|
||||
|
||||
HTTP_INVALID
|
||||
};
|
||||
|
||||
/* struct memstream { */
|
||||
/* FILE *fp; */
|
||||
/* char *buf; */
|
||||
/* size_t len; */
|
||||
/* }; */
|
||||
|
||||
/* struct res { */
|
||||
/* struct memstream head; */
|
||||
/* struct memstream entity; */
|
||||
/* }; */
|
||||
|
||||
/* int res_push_header(struct res *res, const char *key, const char *valfmt, ...) */
|
||||
/* { */
|
||||
/* fprintf */
|
||||
/* } */
|
||||
|
||||
/* int res_respond_to(struct res *res, FCGX_Request *req) */
|
||||
/* { */
|
||||
|
||||
/* } */
|
||||
|
||||
/* int res_init(struct res *res) */
|
||||
/* { */
|
||||
/* res->head.fp = open_memstream(&res->head.buf, &res->head.len); */
|
||||
/* if (!res->head.fp) */
|
||||
/* goto err; */
|
||||
|
||||
/* res->entity.fp = open_memstream(&res->entity.buf, &res->entity.len); */
|
||||
/* if (!res->entity.fp) */
|
||||
/* goto err_free_head; */
|
||||
|
||||
/* return 0; */
|
||||
|
||||
/* err_free_head: */
|
||||
/* fclose(res->head.fp); */
|
||||
/* err: */
|
||||
/* return -ENOMEM; */
|
||||
/* } */
|
||||
|
||||
struct req {
|
||||
FCGX_Request r;
|
||||
|
||||
enum http_method method;
|
||||
char *uri;
|
||||
|
||||
union {
|
||||
struct {
|
||||
char *path;
|
||||
} data;
|
||||
};
|
||||
};
|
||||
|
||||
static enum http_method req_parse_method(struct req *req)
|
||||
{
|
||||
const char *str = FCGX_GetParam("REQUEST_METHOD", req->r.envp);
|
||||
|
||||
if (!str)
|
||||
return HTTP_INVALID;
|
||||
|
||||
if (!strcmp(str, "GET"))
|
||||
return HTTP_GET;
|
||||
if (!strcmp(str, "HEAD"))
|
||||
return HTTP_HEAD;
|
||||
if (!strcmp(str, "PATCH"))
|
||||
return HTTP_PATCH;
|
||||
if (!strcmp(str, "POST"))
|
||||
return HTTP_POST;
|
||||
if (!strcmp(str, "PUT"))
|
||||
return HTTP_PUT;
|
||||
|
||||
return HTTP_INVALID;
|
||||
}
|
||||
|
||||
static int req_init(struct req *req)
|
||||
{
|
||||
const char *uri;
|
||||
|
||||
req->method = req_parse_method(req);
|
||||
|
||||
uri = FCGX_GetParam("REQUEST_URI", req->r.envp);
|
||||
if (!uri)
|
||||
return -EINVAL;
|
||||
|
||||
req->uri = strdup(uri);
|
||||
if (!req->uri)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int req_fini(struct req *req)
|
||||
{
|
||||
free(req->uri);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dumpenv(char **envp)
|
||||
{
|
||||
fprintf(stderr, "ENV:\n");
|
||||
@@ -19,16 +131,19 @@ static void dumpenv(char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
int serve_host_meta(FCGX_Request *req)
|
||||
int serve_host_meta(struct req *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")))
|
||||
switch (req->method) {
|
||||
case HTTP_GET:
|
||||
case HTTP_HEAD:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fp = open_memstream(&buf, &len);
|
||||
if (!fp)
|
||||
@@ -40,61 +155,203 @@ int serve_host_meta(FCGX_Request *req)
|
||||
"</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);
|
||||
FCGX_FPrintF(req->r.out, "Content-Type: application/xrd+xml\r\n");
|
||||
FCGX_FPrintF(req->r.out, "Content-Length: %zd\r\n", len);
|
||||
FCGX_FPrintF(req->r.out, "Connection: close\r\n");
|
||||
FCGX_PutS("\r\n", req->r.out);
|
||||
|
||||
if (!strcmp(method, "GET"))
|
||||
FCGX_PutStr(buf, len, req->out);
|
||||
if (req->method == HTTP_GET)
|
||||
FCGX_PutStr(buf, len, req->r.out);
|
||||
|
||||
free(buf);
|
||||
|
||||
FCGX_Finish_r(req);
|
||||
FCGX_Finish_r(&req->r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serve_restconf(FCGX_Request *req)
|
||||
int hex2bin(char *hex)
|
||||
{
|
||||
FCGX_FPrintF(req->out, "Content-type: text/html\r\n\r\n");
|
||||
FCGX_FPrintF(req->out, "RESTCONF\r\n");
|
||||
FCGX_Finish_r(req);
|
||||
int i, out;
|
||||
|
||||
for (i = 0, out = 0; i < 2; i++) {
|
||||
out <<= 4;
|
||||
|
||||
if (hex[i] >= '0' && hex[i] <= '9')
|
||||
out |= hex[0] - '0';
|
||||
else if (hex[i] >= 'a' && hex[i] <= 'f')
|
||||
out |= hex[0] - 'a';
|
||||
else if (hex[i] >= 'A' && hex[i] <= 'F')
|
||||
out |= hex[0] - 'A';
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (out < 0 || out >= 0x80)
|
||||
/* No UTF-8 support */
|
||||
return -EINVAL;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int unpercent(char *tok)
|
||||
{
|
||||
char *in, *out, *end;
|
||||
int escaped;
|
||||
|
||||
in = out = tok;
|
||||
for (; *in; in++, out++) {
|
||||
if (*in != '%') {
|
||||
*out = *in;
|
||||
continue;
|
||||
}
|
||||
|
||||
escaped = hex2bin(in + 1);
|
||||
if (escaped < 0)
|
||||
return escaped;
|
||||
|
||||
*out = escaped;
|
||||
in += 2;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xpath_from_uri(struct ly_ctx *ly, char *uri, char **xpathp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int uri_resolve_r(sr_data_t **nodep, char **urip, char **toksave)
|
||||
{
|
||||
char *tok;
|
||||
int err;
|
||||
|
||||
tok = strtok_r(*toksave ? NULL : *urip, "/", toksave);
|
||||
if (!tok)
|
||||
return 0;
|
||||
|
||||
err = unpercent(tok);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int uri_resolve(sr_session_ctx_t *sess, char *uri, struct lyd_node **nodep)
|
||||
{
|
||||
sr_data_t *node;
|
||||
char *toksave = NULL;
|
||||
int err;
|
||||
|
||||
err = sr_get_subtree(sess, "/", 0, &node);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = uri_resolve_r(&node, &uri, &toksave);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tok = srst_uritok(uri);
|
||||
if (!tok)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int serve_restconf_data(struct req *req)
|
||||
{
|
||||
sr_session_ctx_t *sess;
|
||||
sr_conn_ctx_t *conn;
|
||||
sr_data_t *data;
|
||||
int err = 0;
|
||||
|
||||
FILE *fp;
|
||||
char *buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (req->method != HTTP_GET) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (sr_connect(SR_CONN_DEFAULT, &conn)) {
|
||||
err = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
|
||||
err = -EIO;
|
||||
goto err_disconnect;
|
||||
}
|
||||
|
||||
|
||||
sr_get_data(sess, req->data.path, 0, 0, 0, &data);
|
||||
|
||||
fp = open_memstream(&buf, &len);
|
||||
lyd_print_file(fp, data ? data->tree : NULL, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
fclose(fp);
|
||||
|
||||
FCGX_FPrintF(req->r.out, "Content-Type: application/yang-data+json\r\n");
|
||||
FCGX_FPrintF(req->r.out, "Content-Length: %zd\r\n", len);
|
||||
FCGX_FPrintF(req->r.out, "Connection: close\r\n");
|
||||
FCGX_PutS("\r\n", req->r.out);
|
||||
|
||||
FCGX_PutStr(buf, len, req->r.out);
|
||||
free(buf);
|
||||
|
||||
FCGX_Finish_r(&req->r);
|
||||
return 0;
|
||||
|
||||
err_disconnect:
|
||||
sr_disconnect(conn);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
int serve_restconf(struct req *req)
|
||||
{
|
||||
char *uri = req->uri + strlen(rootpath);
|
||||
|
||||
if (!strncmp(uri, "data/", strlen("data/"))) {
|
||||
req->data.path = uri + strlen("data/");
|
||||
return serve_restconf_data(req);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int serve(int sd)
|
||||
{
|
||||
FCGX_Request req;
|
||||
const char *uri;
|
||||
struct req req;
|
||||
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)
|
||||
for (FCGX_InitRequest(&req.r, sd, 0);
|
||||
FCGX_Accept_r(&req.r) == 0;
|
||||
FCGX_InitRequest(&req.r, sd, 0)) {
|
||||
if (req_init(&req))
|
||||
continue;
|
||||
|
||||
if (!strcmp(uri, "/.well-known/host-meta"))
|
||||
dumpenv(req.r.envp);
|
||||
|
||||
if (!strcmp(req.uri, "/.well-known/host-meta"))
|
||||
err = serve_host_meta(&req);
|
||||
else if (!strncmp(uri, rootpath, strlen(rootpath)))
|
||||
else if (!strncmp(req.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_FPrintF(req.r.out, "Status: 400 Bad Request\r\n");
|
||||
FCGX_FPrintF(req.r.out, "Content-Type: text/html\r\n");
|
||||
FCGX_FPrintF(req.r.out, "Connection: close\r\n");
|
||||
FCGX_PutS("\r\n", req.r.out);
|
||||
FCGX_Finish_r(&req.r);
|
||||
}
|
||||
|
||||
req_fini(&req);
|
||||
}
|
||||
|
||||
FCGX_Free(&req, sd);
|
||||
FCGX_Free(&req.r, sd);
|
||||
|
||||
if (err)
|
||||
fprintf(stderr, "Unable to handle request: %d\n", err);
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libyang/libyang.h>
|
||||
|
||||
int hex2bin(char *hex)
|
||||
{
|
||||
int i, out;
|
||||
|
||||
for (i = 0, out = 0; i < 2; i++) {
|
||||
out <<= 4;
|
||||
|
||||
if (hex[i] >= '0' && hex[i] <= '9')
|
||||
out |= hex[0] - '0';
|
||||
else if (hex[i] >= 'a' && hex[i] <= 'f')
|
||||
out |= hex[0] - 'a';
|
||||
else if (hex[i] >= 'A' && hex[i] <= 'F')
|
||||
out |= hex[0] - 'A';
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (out < 0 || out >= 0x80)
|
||||
/* No UTF-8 support */
|
||||
return -EINVAL;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int unpercent(char *text)
|
||||
{
|
||||
char *in, *out, *end;
|
||||
int escaped;
|
||||
|
||||
in = out = text;
|
||||
for (; *in; in++, out++) {
|
||||
if (*in != '%') {
|
||||
*out = *in;
|
||||
continue;
|
||||
}
|
||||
|
||||
escaped = hex2bin(in + 1);
|
||||
if (escaped < 0)
|
||||
return escaped;
|
||||
|
||||
*out = escaped;
|
||||
in += 2;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uri_node {
|
||||
char *module;
|
||||
char *name;
|
||||
char *keyv[8];
|
||||
};
|
||||
|
||||
int uri_node_from_seg(char *seg, struct uri_node *n)
|
||||
{
|
||||
int keyc = 0;
|
||||
char *delim;
|
||||
|
||||
memset(n, 0, sizeof(*n));
|
||||
|
||||
delim = strchr(seg, ':');
|
||||
if (delim) {
|
||||
*delim++ = '\0';
|
||||
|
||||
n->module = seg;
|
||||
n->name = seg = delim;
|
||||
} else {
|
||||
n->name = seg;
|
||||
}
|
||||
|
||||
delim = strchr(seg, '=');
|
||||
if (!delim)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
if (keyc >= 7)
|
||||
return -EINVAL;
|
||||
|
||||
*delim++ = '\0';
|
||||
n->keyv[keyc++] = seg = delim;
|
||||
} while ((delim = strchr(seg, ','); keyc++));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xpath_from_uri(struct ly_ctx *ly, char *uri, char **xpathp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user