summaryrefslogtreecommitdiff
path: root/src/sf.eiface/main.c
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.eiface/main.c
Import project
Diffstat (limited to 'src/sf.eiface/main.c')
-rw-r--r--src/sf.eiface/main.c155
1 files changed, 155 insertions, 0 deletions
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 <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);
+ 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();
+}