summaryrefslogtreecommitdiff
path: root/src/sf.jail
diff options
context:
space:
mode:
authordautor <karlo98.m@gmail.com>2024-11-17 20:53:51 +0100
committerdautor <karlo98.m@gmail.com>2024-11-17 20:53:51 +0100
commitf1e579bc427df418af96da61498fe0cdb4cecb69 (patch)
tree1fc8f6b196fbc1cc9166a1e10c74eff83f8f2aab /src/sf.jail
parentc22c6581ee39688785476fe56f2b759ae49ca04a (diff)
Add COPYRIGHT and rename module directories
Diffstat (limited to 'src/sf.jail')
-rw-r--r--src/sf.jail/main.c525
-rw-r--r--src/sf.jail/state.c396
-rw-r--r--src/sf.jail/state.h93
3 files changed, 0 insertions, 1014 deletions
diff --git a/src/sf.jail/main.c b/src/sf.jail/main.c
deleted file mode 100644
index d71511b..0000000
--- a/src/sf.jail/main.c
+++ /dev/null
@@ -1,525 +0,0 @@
-#include "../module/module.h"
-#include "../util.h"
-#include "state.h"
-
-#include <jail.h>
-#include <sys/param.h>
-#include <sys/jail.h>
-
-#include <netgraph.h>
-#include <netgraph/ng_message.h>
-#include <netgraph/ng_eiface.h>
-
-#include <sys/mount.h>
-#include <sys/ioctl.h>
-#include <fs/devfs/devfs.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"
- " %1$s cmd [name] [configuration] [data] sh\n"
- " %1$s cmd [name] [configuration] [data] wireshark [interface]\n"
- "unsupported commands: 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
-}
-
-static int
-start_interface(interface *E, interface_configuration *C, fd Control, char const *JailName)
-{
- E->Type = C->Type;
- switch(C->Type)
- {
- case interface_type_eiface:
- {
- if(Create_eiface(&E->ID, Control) == -1) return -1;
- char *InterfaceName = getifname(E->ID, Control);
- if(InterfaceName == NULL)
- {
- DestroyNetgraphNode(E->ID, Control);
- return -1;
- }
- // NOTE: This first renames the interface and only then vnets it.
- int Result =
- command("ifconfig", "ifconfig", InterfaceName, "name", C->Name, "vnet", JailName, NULL);
- free(InterfaceName);
- return Result;
- }
- case interface_type_steal:
- {
- return command("ifconfig", "ifconfig", C->steal.Interface, "name", C->Name, "vnet", JailName, NULL);
- }
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
-}
-
-static int
-stop_interface(interface *E, interface_configuration *C, fd Control, char const *JailName)
-{
- switch(C->Type)
- {
- case interface_type_eiface: return DestroyNetgraphNode(E->ID, Control);
- case interface_type_steal:
- {
- return command("ifconfig",
- "ifconfig",
- C->Name,
- "-vnet",
- JailName,
- "name",
- C->steal.Interface,
- NULL);
- }
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
-}
-
-static int
-stop_interfaces(interfaces *E, interfaces_configuration *C, fd Control, char const *JailName)
-{
- for(size_t i = 0; i < E->Count; ++i)
- {
- if(stop_interface(E->_ + i, C->_ + i, Control, JailName) == -1)
- {
- fprintf(stderr, "failed to stop interface '%s'\n", C->_[i].Name);
- return -1;
- }
- }
- return 0;
-}
-
-static int
-start_interfaces(interfaces *E, interfaces_configuration *C, fd Control, char const *Name)
-{
- Data.Interfaces._ = calloc(sizeof(interface), Configuration.Interfaces.Count);
- for(E->Count = 0; E->Count < C->Count; ++E->Count)
- {
- interface *E_ = E->_ + E->Count;
- interface_configuration *C_ = C->_ + E->Count;
- if(start_interface(E_, C_, Control, Name) == -1) goto error;
- }
- return 0;
-error:
- stop_interfaces(E, C, Control, Name);
- Free_interfaces(E);
- return -1;
-}
-
-static int
-start_jail(jid_t *JID, char const *Name, char const *Path)
-{
- *JID = jail_setv(JAIL_CREATE, "name", Name, "vnet", "new", "persist", "true", "path", Path, NULL);
- if(*JID == -1)
- {
- fprintf(stderr, "jail creation failed: %s\n", strerror(errno));
- return -1;
- }
- return 0;
-}
-
-static int
-stop_jail(jid_t JID)
-{
- if(jail_remove(JID) == -1)
- {
- fprintf(stderr, "jail removal failed: %s\n", strerror(errno));
- Free_all();
- return -1;
- }
- return 0;
-}
-
-NAMED_ENUM(mapping_type, unionfs_below, unionfs, devfs, nullfs);
-
-static int
-mapping_mount(mapping *M, char const *TargetPrefix, mapping_type Type)
-{
- char Target[MAXPATHLEN];
- snprintf(Target, sizeof(Target), "%s/%s", TargetPrefix, M->Target);
- if(mkdir(Target, 755) == -1)
- {
- if(errno != EEXIST)
- {
- fprintf(stderr, "mkdir %s: %s\n", Target, strerror(errno));
- return -1;
- }
- }
- switch(Type)
- {
- case mapping_type_unionfs_below: return mount_unionfs(Target, M->Source, true);
- case mapping_type_unionfs: return mount_unionfs(Target, M->Source, false);
- case mapping_type_devfs: return mount_devfs(Target);
- case mapping_type_nullfs: return mount_nullfs(Target, M->Source);
- case mapping_type_COUNT:
- default: __builtin_unreachable();
- }
-}
-
-static int
-mapping_umount(char const *TargetPrefix, char const *Target_)
-{
- char Target[MAXPATHLEN];
- snprintf(Target, sizeof(Target), "%s/%s", TargetPrefix, Target_);
- // NOTE: unmount fails because some processes somehow still hold a reference to the jail FS
- while(unmount(Target, MNT_FORCE) == -1)
- {
- fprintf(stderr, "unmount %s failed: %s\n", Target, strerror(errno));
- if(errno != EBUSY) return -1;
- sleep(1);
- }
- return 0;
-}
-
-static int
-rm(char const *Path)
-{
- pid_t PID = fork();
- if(PID == -1) return -1;
- if(PID == 0)
- {
- close(STDIN_FILENO);
- dup2(STDERR_FILENO, STDOUT_FILENO);
- close_all();
- fprintf(stderr, "rm -r %s\n", Path);
- execlp("rm", "rm", "-r", Path, NULL);
- exit(-1);
- }
- int Exit;
- waitpid(PID, &Exit, 0);
- if(!WIFEXITED(Exit) || (WEXITSTATUS(Exit) != 0)) return -1;
- return 0;
-}
-
-static int
-ApplyDevfsRuleset(char const *Prefix, s64 Ruleset)
-{
- if(Ruleset == 0) return 0;
- devfs_rsnum RS = (devfs_rsnum)Ruleset;
- if(RS != Ruleset)
- {
- fprintf(stderr, "Ruleset invalid: %ld\n", Ruleset);
- return -1;
- }
- char Path[MAXPATHLEN];
- snprintf(Path, sizeof(Path), "%s/dev", Prefix);
- fd DevFD = open(Path, O_RDONLY);
- if(DevFD == -1)
- {
- fprintf(stderr, "open '%s' failed: %s\n", Path, strerror(errno));
- return -1;
- }
- if(ioctl(DevFD, DEVFSIO_SAPPLY, &RS) == -1)
- {
- fprintf(stderr, "ruleset %hu apply failed: %s\n", RS, strerror(errno));
- close(DevFD);
- return -1;
- }
- close(DevFD);
- return 0;
-}
-
-static int
-start_fs(filesystem_configuration *E, char const *Path)
-{
- bool CreatedPath = false;
- size_t LayerAt = 0;
- size_t VolumeAt = 0;
- bool Mounted_devfs = false;
- bool Mounted_temporary = false;
- if(mkdir(Path, 0755) == -1)
- {
- fprintf(stderr, "mkdir %s: %s\n", Path, strerror(errno));
- goto error;
- }
- CreatedPath = true;
- for(LayerAt = 0; LayerAt < E->LayerCount; ++LayerAt)
- {
- if(mapping_mount(&(mapping){ .Source = E->Layer[LayerAt], .Target = "/" },
- Path,
- mapping_type_unionfs_below) == -1)
- goto error;
- }
- if(E->Temporary != NULL)
- {
- if(mkdir(E->Temporary, 755) == -1)
- {
- if(errno != EEXIST)
- {
- fprintf(stderr, "mkdir %s: %s\n", E->Temporary, strerror(errno));
- goto error;
- }
- }
- if(mapping_mount(&(mapping){ .Source = E->Temporary, .Target = "/" }, Path, mapping_type_unionfs) == -1)
- goto error;
- }
- Mounted_temporary = true;
- if(mapping_mount(&(mapping){ .Target = "/dev" }, Path, mapping_type_devfs) == -1) goto error;
- if(ApplyDevfsRuleset(Path, E->DevfsRuleset) == -1) goto error;
- for(VolumeAt = 0; VolumeAt < E->VolumeCount; ++VolumeAt)
- {
- if(mapping_mount(E->Volume + VolumeAt, Path, mapping_type_nullfs) == -1) goto error;
- }
- return 0;
-error:
- for(size_t i = 0; i < VolumeAt; ++i) mapping_umount(Path, E->Volume[E->VolumeCount - 1 - i].Target);
- if(Mounted_devfs) mapping_umount(Path, "/dev");
- if(Mounted_temporary) mapping_umount(Path, "/");
- for(size_t i = 0; i < LayerAt; ++i) mapping_umount(Path, "/");
- if(CreatedPath) rm(Path);
- return -1;
-}
-
-static int
-stop_fs(filesystem_configuration *E, char const *Path)
-{
- for(size_t i = 0; i < E->VolumeCount; ++i) mapping_umount(Path, E->Volume[E->VolumeCount - 1 - i].Target);
- mapping_umount(Path, "/dev");
- if(E->Temporary != NULL) mapping_umount(Path, "/");
- for(size_t i = 0; i < E->LayerCount; ++i) mapping_umount(Path, "/");
- if(rm(Path) == -1)
- {
- fprintf(stderr, "rm -r %s: %s\n", Path, strerror(errno));
- goto error;
- }
- return 0;
-error:
- return -1;
-}
-
-static bool
-ValidJailName(char const *Name)
-{
- for(char const *At = Name; *At; ++At)
- {
- if(isnumber(*At) == false) return true;
- }
- return true;
-}
-
-// COMMANDS
-
-static char const *FilesystemPrefix = "/tmp/sf";
-
-int
-start(char const *Name, ucl_object_t *configuration)
-{
- if(ValidJailName(Name) == false) return -1;
- Load_configuration(configuration);
- fd Control = -1;
- Data.JID = -1;
- char Path[PATH_MAX];
- snprintf(Path, sizeof(Path), "%s/%s", FilesystemPrefix, Name);
- if(mkdir(FilesystemPrefix, 0755) == -1)
- {
- if(errno != EEXIST)
- {
- fprintf(stderr, "mkdir %s: %s\n", FilesystemPrefix, strerror(errno));
- goto error;
- }
- }
- if(start_fs(&Configuration.Filesystem, Path) == -1) goto error;
- if(start_jail(&Data.JID, Name, Path) == -1) goto error;
- if(NgMkSockNode(NULL, &Control, NULL) == -1)
- {
- fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
- goto error;
- }
- if(start_interfaces(&Data.Interfaces, &Configuration.Interfaces, Control, Name) == -1)
- {
- fprintf(stderr, "failed to start interfaces\n");
- goto error;
- }
- DataLoaded = true;
- close(Control);
- exec_string_array(&Configuration.Init, false, Data.JID);
- jprint_state S;
- bzero(&S, sizeof(S));
- S.F = stdout;
- Save_data(&S, &Data);
- Free_all();
- return 0;
-error:
- if(Control != -1) close(Control);
- if(Data.JID != -1) stop_jail(Data.JID);
- Free_all();
- return -1;
-}
-
-int
-stop(char const *Name, ucl_object_t *configuration, ucl_object_t *data)
-{
- if(ValidJailName(Name) == false) return -1;
- Load_configuration(configuration);
- Load_data(data);
- exec_string_array(&Configuration.Shutdown, true, Data.JID);
- fd Control = -1;
- if(NgMkSockNode(NULL, &Control, NULL) == -1)
- {
- fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
- goto error;
- }
- if(stop_interfaces(&Data.Interfaces, &Configuration.Interfaces, Control, Name) == -1) goto error;
- if(stop_jail(Data.JID) == -1) goto error;
- char Path[PATH_MAX];
- snprintf(Path, sizeof(Path), "%s/%s", FilesystemPrefix, Name);
- if(stop_fs(&Configuration.Filesystem, Path) == -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)
-{
- if(ValidJailName(Name) == false) return -1;
- Load_configuration(configuration);
- Load_data(data);
- for(size_t i = 0; i < Configuration.Interfaces.Count; ++i)
- {
- interface_configuration *C = Configuration.Interfaces._ + i;
- if(strcmp(C->Name, Interface) == 0)
- {
- interface *E = Data.Interfaces._ + i;
- jprint_state S;
- bzero(&S, sizeof(S));
- S.F = stdout;
- JPrintObjectBegin(&S);
- JPrintMember(&S, "address");
- char Address[NG_PATHSIZ];
- snprintf(Address, sizeof(Address), "[%x]:", E->ID);
- JPrint_string(&S, Address);
- JPrintMember(&S, "hook");
- JPrint_string(&S, "ether");
- JPrintObjectEnd(&S);
- Free_all();
- return 0;
- }
- }
- Free_all();
- return -1;
-}
-
-int
-cmd(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg)
-{
- if(ValidJailName(Name) == false) return -1;
- Load_configuration(configuration);
- Load_data(data);
- if(ArgCount < 1) usage();
- char const *Command = Arg[0];
- --ArgCount;
- ++Arg;
- if(strcmp(Command, "sh") == 0)
- {
- size_t ExtraArguments = 2;
- char **Args = alloca(sizeof(char *) * (ArgCount + ExtraArguments + 1));
- Args[0] = "jexec";
- Args[1] = strdup(Name);
- memcpy(Args + ExtraArguments, Arg, sizeof(char *) * ArgCount);
- Args[ArgCount + ExtraArguments] = NULL;
- execvp("jexec", Args);
- fprintf(stderr, "execvp failed: %s\n", strerror(errno));
- exit(-1);
- } else if(strcmp(Command, "wireshark") == 0)
- {
- if(ArgCount < 1) usage();
- char const *Interface = Arg[0];
- --ArgCount;
- ++Arg;
- fd Pipe[2];
- if(pipe(Pipe) == -1)
- {
- fprintf(stderr, "pipe: %s\n", strerror(errno));
- return -1;
- }
- pid_t PID = fork();
- if(PID == -1)
- {
- fprintf(stderr, "fork: %s\n", strerror(errno));
- return -1;
- } else if(PID == 0)
- {
- dup2(Pipe[1], STDOUT_FILENO);
- close(Pipe[0]);
- close(Pipe[1]);
- close_all();
- if(jail_attach(Data.JID))
- {
- fprintf(stderr, "jail_attach(%d): %s\n", Data.JID, strerror(errno));
- exit(-1);
- }
- execlp("tcpdump", "tcpdump", "-s", "-0", "-U", "-w", "-", "-i", Interface, NULL);
- fprintf(stderr, "execlp failed: %s\n", strerror(errno));
- exit(-1);
- } else
- {
- dup2(Pipe[0], STDIN_FILENO);
- close(Pipe[0]);
- close(Pipe[1]);
- close_all();
- char Title[64];
- snprintf(Title, sizeof(Title), "gui.window_title:%s:%s", Name, Interface);
- execlp("wireshark", "wireshark", "-o", Title, "-k", "-i", "-", NULL);
- fprintf(stderr, "execlp failed: %s\n", strerror(errno));
- exit(-1);
- }
- } else
- {
- fprintf(stderr, "unknown command %s\n", Command);
- usage();
- }
-}
-
-int
-mod(char const *Name, ucl_object_t *configuration, ucl_object_t *data, size_t ArgCount, char **Arg)
-{
- if(ValidJailName(Name) == false) return -1;
- Load_configuration(configuration);
- Load_data(data);
- UNUSED(ArgCount, Arg);
- usage();
-}
diff --git a/src/sf.jail/state.c b/src/sf.jail/state.c
deleted file mode 100644
index 893961e..0000000
--- a/src/sf.jail/state.c
+++ /dev/null
@@ -1,396 +0,0 @@
-#include "state.h"
-
-// FREE
-
-void
-Free_interface_configuration(interface_configuration *E)
-{
- free(E->Name);
- switch(E->Type)
- {
- case interface_type_eiface: break;
- case interface_type_steal: free(E->steal.Interface); break;
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
-}
-
-void
-Free_interfaces_configuration(interfaces_configuration *E)
-{
- for(size_t i = 0; i < E->Count; ++i) Free_interface_configuration(E->_ + i);
- free(E->_);
-}
-
-void
-Free_mapping(mapping *E)
-{
- free(E->Source);
- free(E->Target);
-}
-
-void
-Free_filesystem_configuration(filesystem_configuration *E)
-{
- for(size_t i = 0; i < E->LayerCount; ++i) free(E->Layer[i]);
- if(E->Layer != NULL) free(E->Layer);
- if(E->Temporary != NULL) free(E->Temporary);
- for(size_t i = 0; i < E->VolumeCount; ++i) Free_mapping(E->Volume + i);
- if(E->Volume != NULL) free(E->Volume);
-}
-
-void
-Free_configuration(configuration *E)
-{
- Free_filesystem_configuration(&E->Filesystem);
- Free_interfaces_configuration(&E->Interfaces);
- Free_string_array(&E->Init);
- Free_string_array(&E->Shutdown);
-}
-
-void
-Free_interface(interface *E)
-{
- UNUSED(E);
-}
-
-void
-Free_interfaces(interfaces *E)
-{
- for(size_t i = 0; i < E->Count; ++i) Free_interface(E->_ + i);
- free(E->_);
-}
-
-void
-Free_data(data *E)
-{
- Free_interfaces(&E->Interfaces);
-}
-
-// PARSE
-
-char *
-Parse_interface_type(interface_type *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(STRING);
- char const *Type = ucl_object_tostring(root);
- for(interface_type i = 0; i < interface_type_COUNT; ++i)
- {
- if(strcmp(interface_type_Names[i], Type) == 0)
- {
- *E = i;
- return NULL;
- }
- }
- asprintf(&Error, "%s invalid interface type '%s'", Position, Type);
- goto error;
-error:
- return Error;
-}
-
-char *
-Parse_interface_configuration(interface_configuration *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.type", Position);
- Error = Parse_interface_type(&E->Type, ucl_object_lookup(root, "type"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- switch(E->Type)
- {
- case interface_type_eiface: break;
- case interface_type_steal:
- {
- ucl_object_t const *interface = ucl_object_lookup(root, "interface");
- UCL_CHECK(interface, STRING);
- E->steal.Interface = strdup(ucl_object_tostring(interface));
- break;
- }
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
- return NULL;
-error:
- return Error;
-}
-
-char *
-Parse_interfaces_configuration(interfaces_configuration *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- E->Count = root->len;
- E->_ = calloc(sizeof(interface_configuration), E->Count);
- {
- ucl_object_iter_t it = NULL;
- for(E->Count = 0; E->Count < root->len; ++E->Count)
- {
- ucl_object_t const *v = ucl_iterate_object(root, &it, true);
- if(v == NULL) break;
- char const *k = ucl_object_key(v);
- if(k == NULL) continue;
- interface_configuration *I = E->_ + E->Count;
- char *NewPosition;
- asprintf(&NewPosition, "%s['%s']", Position, k);
- Error = Parse_interface_configuration(I, v, NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- I->Name = strdup(k);
- }
- }
- return NULL;
-error:
- Free_interfaces_configuration(E);
- return Error;
-}
-
-char *
-Parse_mapping(mapping *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- ucl_object_t const *source = ucl_object_lookup(root, "source");
- UCL_CHECK(source, STRING);
- ucl_object_t const *target = ucl_object_lookup(root, "target");
- UCL_CHECK(target, STRING);
- E->Source = strdup(ucl_object_tostring(source));
- E->Target = strdup(ucl_object_tostring(target));
- return NULL;
-error:
- return Error;
-}
-
-char *
-Parse_filesystem_configuration(filesystem_configuration *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- ucl_object_t const *layers = ucl_object_lookup(root, "layers");
- UCL_CHECK_OPTIONAL(layers, ARRAY);
- ucl_object_t const *temporary = ucl_object_lookup(root, "temporary");
- UCL_CHECK_OPTIONAL(temporary, STRING);
- ucl_object_t const *volumes = ucl_object_lookup(root, "volumes");
- UCL_CHECK_OPTIONAL(volumes, ARRAY);
- ucl_object_t const *devfs = ucl_object_lookup(root, "devfs");
- UCL_CHECK_OPTIONAL(devfs, INT);
- if(layers != NULL)
- {
- E->Layer = calloc(sizeof(char *), layers->len);
- ucl_object_iter_t it = NULL;
- for(E->LayerCount = 0; E->LayerCount < layers->len; ++E->LayerCount)
- {
- ucl_object_t const *v = ucl_iterate_object(layers, &it, true);
- if(v == NULL) break;
- char const *k = ucl_object_key(v);
- if(k != NULL) continue;
- if(v->type != UCL_STRING)
- {
- asprintf(&Error, "%s.layers[%zu] is not " UCL_CHECK_HELPER(STRING), Position, E->LayerCount);
- goto error;
- }
- E->Layer[E->LayerCount] = strdup(ucl_object_tostring(v));
- }
- }
- if(temporary != NULL) E->Temporary = strdup(ucl_object_tostring(temporary));
- if(volumes != NULL)
- {
- E->Volume = calloc(sizeof(mapping), volumes->len);
- ucl_object_iter_t it = NULL;
- for(E->VolumeCount = 0; E->VolumeCount < volumes->len; ++E->VolumeCount)
- {
- ucl_object_t const *v = ucl_iterate_object(volumes, &it, true);
- if(v == NULL) break;
- char const *k = ucl_object_key(v);
- if(k != NULL) continue;
- mapping *I = E->Volume + E->VolumeCount;
- char *NewPosition;
- asprintf(&NewPosition, "%s.volumes[%zu]", Position, E->VolumeCount);
- Error = Parse_mapping(I, v, NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- }
- E->DevfsRuleset = ucl_object_toint(devfs);
- return NULL;
-error:
- Free_filesystem_configuration(E);
- return Error;
-}
-
-char *
-Parse_configuration(configuration *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.interfaces", Position);
- Error =
- Parse_interfaces_configuration(&E->Interfaces, ucl_object_lookup(root, "interfaces"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.filesystem", Position);
- Error =
- Parse_filesystem_configuration(&E->Filesystem, ucl_object_lookup(root, "filesystem"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.init", Position);
- Error = Parse_string_array(&E->Init, ucl_object_lookup(root, "init"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.shutdown", Position);
- Error = Parse_string_array(&E->Shutdown, ucl_object_lookup(root, "shutdown"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- return NULL;
-error:
- return Error;
-}
-
-char *
-Parse_interface(interface *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(OBJECT);
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.type", Position);
- Error = Parse_interface_type(&E->Type, ucl_object_lookup(root, "type"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- switch(E->Type)
- {
- case interface_type_eiface:
- {
- ucl_object_t const *id = ucl_object_lookup(root, "id");
- UCL_CHECK(id, INT);
- s64 ID = ucl_object_toint(id);
- if(ID < 0 || ID > INT32_MAX)
- {
- asprintf(&Error, "%s id invalid (%ld)", Position, ID);
- goto error;
- }
- E->ID = (u32)ID;
- break;
- }
- case interface_type_steal: break;
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
- return NULL;
-error:
- return Error;
-}
-
-char *
-Parse_interfaces(interfaces *E, ucl_object_t const *root, char const *Position)
-{
- char *Error;
- UCL_CHECK_ROOT(ARRAY);
- E->Count = root->len;
- E->_ = calloc(sizeof(interface_configuration), E->Count);
- {
- ucl_object_iter_t it = NULL;
- for(E->Count = 0; E->Count < root->len; ++E->Count)
- {
- ucl_object_t const *v = ucl_iterate_object(root, &it, true);
- if(v == NULL) break;
- char const *k = ucl_object_key(v);
- if(k != NULL) continue;
- interface *I = E->_ + E->Count;
- char *NewPosition;
- asprintf(&NewPosition, "%s['%zu']", Position, E->Count);
- Error = Parse_interface(I, v, NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- }
- return NULL;
-error:
- Free_interfaces(E);
- 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 *jid = ucl_object_lookup(root, "jid");
- UCL_CHECK(jid, INT);
- int64_t JID = ucl_object_toint(jid);
- if(JID < 0 || JID > INT32_MAX)
- {
- asprintf(&Error, "%s jid invalid (%ld)", Position, JID);
- goto error;
- }
- E->JID = (jid_t)JID;
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.interfaces", Position);
- Error = Parse_interfaces(&E->Interfaces, ucl_object_lookup(root, "interfaces"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
- return NULL;
-error:
- return Error;
-}
-
-// SAVE
-
-void
-Save_interface(jprint_state *S, interface const *E)
-{
- JPrintObjectBegin(S);
- JPrintMember(S, "type");
- JPrint_string(S, interface_type_Names[E->Type]);
- switch(E->Type)
- {
- case interface_type_eiface:
- {
- JPrintMember(S, "id");
- JPrint_ssize_t(S, E->ID);
- break;
- }
- case interface_type_steal: break;
- case interface_type_COUNT:
- default: __builtin_unreachable();
- }
- JPrintObjectEnd(S);
-}
-
-void
-Save_interfaces(jprint_state *S, interfaces const *E)
-{
- JPrintArrayBegin(S);
- for(size_t i = 0; i < E->Count; ++i) Save_interface(S, E->_ + i);
- JPrintArrayEnd(S);
-}
-
-void
-Save_data(jprint_state *S, data const *E)
-{
- JPrintObjectBegin(S);
- JPrintMember(S, "jid");
- JPrint_ssize_t(S, E->JID);
- JPrintMember(S, "interfaces");
- Save_interfaces(S, &E->Interfaces);
- JPrintObjectEnd(S);
-}
diff --git a/src/sf.jail/state.h b/src/sf.jail/state.h
deleted file mode 100644
index d22d374..0000000
--- a/src/sf.jail/state.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-#include "../util.h"
-
-NAMED_ENUM(interface_type, eiface, steal);
-
-struct
-{
- char *Name;
- interface_type Type;
- union
- {
- struct
- {
- } eiface;
- struct
- {
- char *Interface;
- } steal;
- };
-} typedef interface_configuration;
-
-struct
-{
- size_t Count;
- interface_configuration *_;
-} typedef interfaces_configuration;
-
-struct
-{
- char *Source;
- char *Target;
-} typedef mapping;
-
-struct
-{
- size_t LayerCount;
- char **Layer;
- char *Temporary;
- size_t VolumeCount;
- mapping *Volume;
- s64 DevfsRuleset;
-} typedef filesystem_configuration;
-
-struct
-{
- interfaces_configuration Interfaces;
- filesystem_configuration Filesystem;
- string_array Init;
- string_array Shutdown;
-} typedef configuration;
-
-struct
-{
- u32 ID;
- interface_type Type;
-} typedef interface;
-
-struct
-{
- size_t Count;
- interface *_;
-} typedef interfaces;
-
-struct
-{
- interfaces Interfaces;
- jid_t JID;
-} typedef data;
-
-void Free_interface_configuration(interface_configuration *);
-void Free_interfaces_configuration(interfaces_configuration *);
-void Free_mapping(mapping *);
-void Free_filesystem_configuration(filesystem_configuration *);
-void Free_configuration(configuration *);
-void Free_interface(interface *);
-void Free_interfaces(interfaces *);
-void Free_data(data *);
-
-char *Parse_interface_type(interface_type *, ucl_object_t const *, char const *Position);
-char *Parse_interface_configuration(interface_configuration *, ucl_object_t const *, char const *Position);
-char *Parse_interfaces_configuration(interfaces_configuration *, ucl_object_t const *, char const *Position);
-char *Parse_mapping(mapping *, ucl_object_t const *, char const *Position);
-char *Parse_filesystem_configuration(filesystem_configuration *, ucl_object_t const *, char const *Position);
-char *Parse_configuration(configuration *, ucl_object_t const *, char const *Position);
-char *Parse_interface(interface *, ucl_object_t const *, char const *Position);
-char *Parse_interfaces(interfaces *, ucl_object_t const *, char const *Position);
-char *Parse_data(data *, ucl_object_t const *, char const *Position);
-
-void Save_interface_type(jprint_state *, interface_type const *);
-void Save_interface(jprint_state *, interface const *);
-void Save_interfaces(jprint_state *, interfaces const *);
-void Save_data(jprint_state *, data const *);