From 47778ccd67cbb3fb70dda706911d3166038ca010 Mon Sep 17 00:00:00 2001 From: dautor Date: Sat, 16 Nov 2024 13:22:54 +0100 Subject: Import project --- src/sf.eiface/main.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/sf.eiface/state.c | 63 ++++++++++++++++++++ src/sf.eiface/state.h | 21 +++++++ 3 files changed, 239 insertions(+) create mode 100644 src/sf.eiface/main.c create mode 100644 src/sf.eiface/state.c create mode 100644 src/sf.eiface/state.h (limited to 'src/sf.eiface') diff --git a/src/sf.eiface/main.c b/src/sf.eiface/main.c new file mode 100644 index 0000000..4fafa81 --- /dev/null +++ b/src/sf.eiface/main.c @@ -0,0 +1,155 @@ +#include "../module/module.h" +#include "../util.h" +#include "state.h" + +#include + +char const *Usage = "usage: %1$s start [name] [configuration]\n" + " %1$s stop [name] [configuration] [data]\n" + " %1$s get-endpoint [name] [configuration] [data] [interface]\n" + "unsupported commands: cmd mod\n"; + +static configuration Configuration; +static data Data; +static bool ConfigurationLoaded; +static bool DataLoaded; + +// HELPERS + +static void +Free_all(void) +{ + if(ConfigurationLoaded == true) Free_configuration(&Configuration); + if(DataLoaded == true) Free_data(&Data); +} + +static void +Load_configuration(ucl_object_t *root) +{ + char *Error = Parse_configuration(&Configuration, root, ""); + if(Error != NULL) + { + fprintf(stderr, "%s: configuration error: %s\n", Arg0, Error); + free(Error); + Free_all(); + exit(-1); + } + ConfigurationLoaded = true; +} + +static void +Load_data(ucl_object_t *root) +{ + char *Error = Parse_data(&Data, root, ""); + if(Error != NULL) + { + fprintf(stderr, "%s: data error: %s\n", Arg0, Error); + free(Error); + Free_all(); + exit(-1); + } + DataLoaded = true; + // TODO: check that data matches configuration +} + +// COMMANDS + +int +start(char const *Name, ucl_object_t *configuration) +{ + UNUSED(Name); + Load_configuration(configuration); + Data.ID = 0; + fd Control = -1; + if(NgMkSockNode(NULL, &Control, NULL) == -1) + { + fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno)); + goto error; + } + if(Create_eiface(&Data.ID, Control) == -1) goto error; + char *InterfaceName = getifname(Data.ID, Control); + if(InterfaceName == NULL) goto error; + int Result = command("ifconfig", "ifconfig", InterfaceName, "name", Name, NULL); + free(InterfaceName); + if(Result == -1) goto error; + close(Control); + if(Configuration.inet != NULL) command("ifconfig", "ifconfig", Name, "inet", Configuration.inet, NULL); + jprint_state S; + bzero(&S, sizeof(S)); + S.F = stdout; + Save_data(&S, &Data); + Free_all(); + return 0; +error: + if(Data.ID != 0) DestroyNetgraphNode(Data.ID, Control); + if(Control != -1) close(Control); + Free_all(); + return -1; +} + +int +stop(char const *Name, ucl_object_t *configuration, ucl_object_t *data) +{ + UNUSED(Name); + Load_configuration(configuration); + Load_data(data); + fd Control = -1; + if(NgMkSockNode(NULL, &Control, NULL) == -1) + { + fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno)); + goto error; + } + if(DestroyNetgraphNode(Data.ID, Control) == -1) goto error; + Free_all(); + return 0; +error: + Free_all(); + return -1; +} + +int +get_endpoint(char const *Name, ucl_object_t *configuration, ucl_object_t *data, char const *Interface) +{ + UNUSED(Name); + Load_configuration(configuration); + Load_data(data); + if(*Interface != '\0') + { + fprintf(stderr, "%s provides only empty interface name\n", Arg0); + goto error; + } + jprint_state S; + bzero(&S, sizeof(S)); + S.F = stdout; + JPrintObjectBegin(&S); + JPrintMember(&S, "address"); + char Address[NG_PATHSIZ]; + snprintf(Address, sizeof(Address), "[%x]:", Data.ID); + JPrint_string(&S, Address); + JPrintMember(&S, "hook"); + JPrint_string(&S, "ether"); + JPrintObjectEnd(&S); + Free_all(); + return 0; +error: + Free_all(); + return -1; +} + +int +cmd(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg) +{ + UNUSED(Name, ArgCount, Arg); + Load_configuration(configuration); + Load_data(data); + usage(); +} + +int +mod(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg) +{ + UNUSED(Name, ArgCount, Arg); + Load_configuration(configuration); + Load_data(data); + usage(); +} diff --git a/src/sf.eiface/state.c b/src/sf.eiface/state.c new file mode 100644 index 0000000..7d85056 --- /dev/null +++ b/src/sf.eiface/state.c @@ -0,0 +1,63 @@ +#include "state.h" + +// FREE + +void +Free_configuration(configuration *E) +{ + if(E->inet != NULL) free(E->inet); +} + +void +Free_data(data *E) +{ + UNUSED(E); +} + +// PARSE + +char * +Parse_configuration(configuration *E, ucl_object_t const *root, char const *Position) +{ + char *Error; + UCL_CHECK_ROOT(OBJECT); + ucl_object_t const *inet = ucl_object_lookup(root, "inet"); + if(inet != NULL) + { + UCL_CHECK(inet, STRING); + E->inet = strdup(ucl_object_tostring(inet)); + } + return NULL; +error: + return Error; +} + +char * +Parse_data(data *E, ucl_object_t const *root, char const *Position) +{ + char *Error; + UCL_CHECK_ROOT(OBJECT); + ucl_object_t const *id = ucl_object_lookup(root, "id"); + UCL_CHECK(id, INT); + s64 ID = ucl_object_toint(id); + if(ID < 0 || ID > UINT32_MAX) + { + asprintf(&Error, "%s id invalid (%ld)", Position, ID); + goto error; + } + E->ID = (u32)ID; + return NULL; +error: + return Error; +} + +// SAVE + +void +Save_data(jprint_state *S, data const *E) +{ + JPrintObjectBegin(S); + JPrintMember(S, "id"); + JPrint_ssize_t(S, E->ID); + JPrintObjectEnd(S); +} diff --git a/src/sf.eiface/state.h b/src/sf.eiface/state.h new file mode 100644 index 0000000..0431fdf --- /dev/null +++ b/src/sf.eiface/state.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../jprint.h" + +struct +{ + char *inet; +} typedef configuration; + +struct +{ + u32 ID; +} typedef data; + +void Free_configuration(configuration *); +void Free_data(data *); + +char *Parse_configuration(configuration *, ucl_object_t const *, char const *Position); +char *Parse_data(data *, ucl_object_t const *, char const *Position); + +void Save_data(jprint_state *, data const *); -- cgit v1.2.3