summaryrefslogtreecommitdiff
path: root/src/sf.bridge
diff options
context:
space:
mode:
authordautor <karlo98.m@gmail.com>2024-11-16 13:22:54 +0100
committerdautor <karlo98.m@gmail.com>2024-11-16 17:54:38 +0100
commit47778ccd67cbb3fb70dda706911d3166038ca010 (patch)
tree906bf0537d14f5ce8e2528736fb89a3499ada214 /src/sf.bridge
Import project
Diffstat (limited to 'src/sf.bridge')
-rw-r--r--src/sf.bridge/main.c166
-rw-r--r--src/sf.bridge/state.c58
-rw-r--r--src/sf.bridge/state.h20
3 files changed, 244 insertions, 0 deletions
diff --git a/src/sf.bridge/main.c b/src/sf.bridge/main.c
new file mode 100644
index 0000000..fbfb500
--- /dev/null
+++ b/src/sf.bridge/main.c
@@ -0,0 +1,166 @@
+#include "../module/module.h"
+#include "../util.h"
+#include "state.h"
+
+#include <netgraph.h>
+
+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);
+ // Implement
+ 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_bridge(&Data.ID, Control) == -1) goto error;
+ close(Control);
+ jprint_state S;
+ bzero(&S, sizeof(S));
+ S.F = stdout;
+ Save_data(&S, &Data);
+ Free_all();
+ return 0;
+error:
+ 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);
+ size_t linkNum;
+ if(strncmp(Interface, "link", __builtin_strlen("link")) == 0)
+ {
+ char const *N = Interface + __builtin_strlen("link");
+ linkNum = strtoul(N, NULL, 10);
+ if(linkNum == 0 && errno == EINVAL)
+ {
+ fprintf(stderr, "invalid interface %s\n", Interface);
+ goto error;
+ }
+ } else if(strncmp(Interface, "uplink", __builtin_strlen("uplink")) == 0)
+ {
+ char const *N = Interface + __builtin_strlen("uplink");
+ linkNum = strtoul(N, NULL, 10);
+ if(linkNum == 0)
+ {
+ fprintf(stderr, "unknown interface %s\n", Interface);
+ goto error;
+ }
+ } else
+ {
+ fprintf(stderr, "unknown interface %s\n", Interface);
+ }
+ 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, Interface);
+ 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.bridge/state.c b/src/sf.bridge/state.c
new file mode 100644
index 0000000..c7780f3
--- /dev/null
+++ b/src/sf.bridge/state.c
@@ -0,0 +1,58 @@
+#include "state.h"
+
+// FREE
+
+void
+Free_configuration(configuration *E)
+{
+ UNUSED(E);
+}
+
+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);
+ UNUSED(E);
+ 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.bridge/state.h b/src/sf.bridge/state.h
new file mode 100644
index 0000000..7ef6243
--- /dev/null
+++ b/src/sf.bridge/state.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "../jprint.h"
+
+struct
+{
+} 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 *);