Skip to content

Commit

Permalink
Merge pull request #94 from jestabro/vyconf-minimal
Browse files Browse the repository at this point in the history
T6718: use the vyconf daemon for validation of set commands
  • Loading branch information
jestabro authored Nov 19, 2024
2 parents 2f5045e + a428d47 commit 3b02b08
Show file tree
Hide file tree
Showing 3 changed files with 297 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ src_libvyatta_cfg_la_SOURCES += src/cnode/cnode-algorithm.cpp
src_libvyatta_cfg_la_SOURCES += src/cparse/cparse.cpp
src_libvyatta_cfg_la_SOURCES += src/cparse/cparse_lex.c
src_libvyatta_cfg_la_SOURCES += src/commit/commit-algorithm.cpp
src_libvyatta_cfg_la_SOURCES += src/vy_adapter.cpp
CLEANFILES = src/cli_parse.c src/cli_parse.h src/cli_def.c src/cli_val.c
CLEANFILES += src/cparse/cparse.cpp src/cparse/cparse.h
CLEANFILES += src/cparse/cparse_lex.c
Expand All @@ -61,6 +62,7 @@ LDADD += $(GOBJECT_LIBS)

vincludedir = $(includedir)/vyatta-cfg
vinclude_HEADERS = src/cli_cstore.h
vinclude_HEADERS += src/vy_adapter.h

vcincdir = $(vincludedir)/cstore
vcinc_HEADERS = src/cstore/cstore-c.h
Expand Down
262 changes: 262 additions & 0 deletions src/vy_adapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#include <cstring>
#include <cstdlib>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <cstdint>
#include <cassert>
#include <algorithm>
#include <list>
#include <fcntl.h>
#include <unistd.h>

#include <cstore/cstore.hpp>
#include <vy_adapter.h>

using namespace cstore;

enum PIPES { READ, WRITE };

extern FILE *out_stream;

class stdout_redirect {
public:
stdout_redirect(): old_stdout(0), redirecting(false) {
out_pipe[READ] = 0;
out_pipe[WRITE] = 0;
if (pipe(out_pipe) == -1) {
return;
}

old_stdout = dup(fileno(stdout));
setbuf(stdout, NULL);
dup2(out_pipe[WRITE], fileno(stdout));

redirecting = true;
}

std::string get_redirected_output() {
if (!redirecting) {
return "";
}

char buffer[1024];
ssize_t bytesRead = 0;
std::string redirected_output = "\n";
fcntl(out_pipe[READ], F_SETFL, O_NONBLOCK);
while ((bytesRead = read(out_pipe[READ], buffer, sizeof(buffer))) > 0) {
redirected_output.append(buffer, bytesRead);
}

return redirected_output;
}

~stdout_redirect() {
if (!redirecting) {
return;
}

dup2(old_stdout, fileno(stdout));

if (old_stdout > 0) {
close(old_stdout);
}
if (out_pipe[READ] > 0) {
close(out_pipe[READ]);
}
if (out_pipe[WRITE] > 0) {
close(out_pipe[WRITE]);
}
}

private:
int out_pipe[2];
int old_stdout;
bool redirecting;
};

struct cstore_obj {
Cstore *cstore;
std::list<char *> output;
};

static struct cstore_obj* create_handle() {
struct cstore_obj *h = new cstore_obj;
h->cstore = Cstore::createCstore(false);
return h;
};

const char *out_data_copy(std::string msg, cstore_obj *o)
{
size_t len = msg.length();
char *out_data = (char *) malloc(len + 1);
o->output.push_back(out_data);
msg.copy(out_data, len);
out_data[len] = '\0';
return out_data;
}

static uint64_t uint_of_voidptr(void* p)
{
assert (((uintptr_t) p & 1) == 0);
return (uint64_t) p | 1;
}

static void *voidptr_of_uint(uint64_t v)
{
return (void *)(uintptr_t)(v & ~1);
}

static cstore_obj *cstore_obj_of_handle(uint64_t handle)
{
return (cstore_obj *) voidptr_of_uint(handle);
}

uint64_t
vy_cstore_init(void)
{
cstore_obj *handle = create_handle();
return uint_of_voidptr(handle);
}

void
vy_cstore_free(uint64_t handle)
{
cstore_obj *h = cstore_obj_of_handle(handle);
for (char * x: h->output) {
free(x);
}
delete h->cstore;
delete h;
}

int
vy_in_session(uint64_t handle)
{
Cstore *h = cstore_obj_of_handle(handle)->cstore;
return h->inSession() ? 1 : 0;
}

const char *
vy_validate_path(uint64_t handle, const void** path_ptr, size_t len)
{
cstore_obj *obj = cstore_obj_of_handle(handle);
Cstore *cstore = obj->cstore;
const char **path = (const char **) path_ptr;
Cpath path_comps = Cpath(path, len);
const char *out_data;
std::string out_str = "";
int res;

out_stream = stdout;
stdout_redirect redirect = stdout_redirect();

res = cstore->validateSetPath(path_comps);
if (!res) {
out_str = "\nInvalid set path: " + path_comps.to_string() + "\n";
out_str.append(redirect.get_redirected_output());
}

out_data = out_data_copy(out_str, obj);
out_stream = NULL;
return out_data;
}

const char *
vy_set_path(uint64_t handle, const void** path_ptr, size_t len)
{
cstore_obj *obj = cstore_obj_of_handle(handle);
Cstore *cstore = obj->cstore;
const char **path = (const char **) path_ptr;
Cpath path_comps = Cpath(path, len);
const char *out_data;
std::string out_str = "";
int res;

out_stream = stdout;
stdout_redirect redirect = stdout_redirect();

res = cstore->setCfgPath(path_comps);
if (!res) {
out_str = "\nSet config path failed: " + path_comps.to_string() + "\n";
out_str.append(redirect.get_redirected_output());
}

out_data = out_data_copy(out_str, obj);
out_stream = NULL;
return out_data;
}

const char *
vy_legacy_set_path(uint64_t handle, const void** path_ptr, size_t len)
{
cstore_obj *obj = cstore_obj_of_handle(handle);
Cstore *cstore = obj->cstore;
const char **path = (const char **) path_ptr;
Cpath path_comps = Cpath(path, len);
const char *out_data;
std::string out_str = "";
int res;

out_stream = stdout;
stdout_redirect redirect = stdout_redirect();

res = cstore->validateSetPath(path_comps);
if (!res) {
out_str = "\nInvalid set path: " + path_comps.to_string() + "\n";
out_str.append(redirect.get_redirected_output());
goto out;
}

res = cstore->setCfgPath(path_comps);
if (!res) {
out_str = "\nSet config path failed: " + path_comps.to_string() + "\n";
out_str.append(redirect.get_redirected_output());
}

out:
out_data = out_data_copy(out_str, obj);
out_stream = NULL;
return out_data;
}

const char *
vy_delete_path(uint64_t handle, const void** path_ptr, size_t len)
{
cstore_obj *obj = cstore_obj_of_handle(handle);
Cstore *cstore = obj->cstore;
const char **path = (const char **) path_ptr;
Cpath path_comps = Cpath(path, len);
const char *out_data;
std::string out_str = "";
int res;

out_stream = stdout;
stdout_redirect redirect = stdout_redirect();

res = cstore->deleteCfgPath(path_comps);
if (!res) {
out_str = "\nDelete failed: " + path_comps.to_string() + "\n";
out_str.append(redirect.get_redirected_output());
}

out_data = out_data_copy(out_str, obj);
out_stream = NULL;
return out_data;
}
33 changes: 33 additions & 0 deletions src/vy_adapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _VY_ADAPTER_H_
#define _VY_ADAPTER_H_
#ifdef __cplusplus
extern "C" {
#endif

uint64_t vy_cstore_init(void);
void vy_cstore_free(uint64_t);
int vy_in_session(uint64_t);
const char *vy_validate_path(uint64_t, const void **, size_t);
const char *vy_set_path(uint64_t, const void **, size_t);
const char *vy_legacy_set_path(uint64_t, const void **, size_t);
const char *vy_delete_path(uint64_t, const void **, size_t);

#ifdef __cplusplus
}
#endif
#endif

0 comments on commit 3b02b08

Please sign in to comment.