Cfg_init(struct Configuration *cfg)
{
Vector_init(&cfg->interfaces, sizeof(struct Interface));
+ cfg->vdir = 0;
+ cfg->xid = VC_DYNAMIC_XID;
cfg->broadcast = 0;
}
}
static inline bool
-getInterfaces(struct Configuration *c, PathInfo const *cfgdir)
+getInterfaces(struct Configuration *cfg)
{
ENSC_PI_DECLARE(iface_subdir, "interfaces");
- PathInfo ifacepath = *cfgdir;
+ PathInfo ifacepath = cfg->cfgdir;
char path_buf[ENSC_PI_APPSZ(ifacepath, iface_subdir)];
struct Interface iface_default;
DIR *dir;
if (!getSingleInterface(&iface, &iface_default, &ifacepath, ent->d_name))
rc = false;
else if (iface.addr.ipv4.ip!=0) { // HACK: non-directory entries would return true also
- struct Interface *new_iface = Vector_pushback(&c->interfaces);
+ struct Interface *new_iface = Vector_pushback(&cfg->interfaces);
*new_iface = iface;
}
}
return rc;
}
+static bool
+initVdir(char const **vdir, PathInfo const *cfgdir)
+{
+ *vdir = vc_getVserverVdir(cfgdir->d, vcCFG_RECENT_FULL, true);
+ if (*vdir==0) {
+ WRITE_MSG(2, "Can not find root-directory of the vserver");
+ return false;
+ }
+
+ return true;
+}
+
bool
-getConfiguration(struct Configuration *c, PathInfo const *cfgdir)
+getConfiguration(struct Configuration *cfg, PathInfo const *cfgdir)
{
- return getInterfaces(c, cfgdir);
+ cfg->cfgdir = *cfgdir;
+
+ return (initVdir(&cfg->vdir, cfgdir) &&
+ getInterfaces(cfg));
}
#ifndef H_UTIL_VSERVER_VSERVER_START_CONFIGURATION_H
#define H_UTIL_VSERVER_VSERVER_START_CONFIGURATION_H
+#include <lib/vserver.h>
#include <ensc_vector/vector.h>
#include <lib_internal/pathinfo.h>
#include <stdbool.h>
struct Configuration {
+ PathInfo cfgdir;
+ char const * vdir;
+ xid_t xid;
uint32_t broadcast;
struct Vector interfaces;
};
{
struct Command cmd;
unsigned int prefix = Iface_getIPv4Prefix(iface);
- char buf[sizeof("255.255.255.255/") + sizeof(unsigned int)*3 + 1];
char * tmp = inet_ntoa(*reinterpret_cast(struct in_addr *)(&iface->addr.ipv4.ip));
size_t l = strlen(tmp);
+ char addr[l + sizeof("/") + sizeof(unsigned int)*3 + 1];
char * ptr;
+ size_t l1 = strlen(iface->dev);
+ size_t l2 = iface->name ? strlen(iface->name) : 0;
+ char devlabel[l1 + l2 + sizeof(":")];
+ bool result = true;
- if (l>=sizeof("255.255.255.255")) {
- abort();
- return false;
- }
- ptr = Xmemcpy(buf, tmp, l);
+ ptr = Xmemcpy(addr, tmp, l);
*ptr++ = '/';
l = utilvserver_fmt_uint(ptr, prefix);
ptr[l] = '\0';
- Command_init(&cmd, 5);
- Command_appendParameter(&cmd, "/bin/echo");
- Command_appendParameter(&cmd, PROG_IP);
- Command_appendParameter(&cmd, buf);
- Command_appendParameter(&cmd, "broadcast");
+ Command_init(&cmd);
+
+ size_t idx = 6;
+ char const * argv[] = {
+ "/bin/echo",
+ PROG_IP, "addr", "add",
+ addr,
+ "broadcast", 0,
+ 0, 0, // label <name>
+ 0, 0, // dev <dev>
+ 0
+ };
+
if (iface->addr.ipv4.bcast!=0)
- Command_appendParameter(&cmd, inet_ntoa(*reinterpret_cast(struct in_addr *)(&iface->addr.ipv4.bcast)));
+ argv[idx++] = inet_ntoa(*reinterpret_cast(struct in_addr *)(&iface->addr.ipv4.bcast));
else
- Command_appendParameter(&cmd, "+");
-
- size_t l1 = strlen(iface->dev);
- size_t l2 = iface->name ? strlen(iface->name) : 0;
- char devlabel[l1 + l2 + sizeof(":")];
+ argv[idx++] = "+";
if (iface->name) {
ptr = Xmemcpy(devlabel, iface->dev, l1);
ptr = Xmemcpy(ptr, iface->name, l2);
*ptr = '\0';
- Command_appendParameter(&cmd, "label");
- Command_appendParameter(&cmd, devlabel);
+ argv[idx++] = "label";
+ argv[idx++] = devlabel;
}
- Command_appendParameter(&cmd, "dev");
- Command_appendParameter(&cmd, iface->dev);
+ argv[idx++] = "dev";
+ argv[idx++] = iface->dev;
+ Command_setParams(&cmd, argv);
if (!Command_exec(&cmd, true) ||
- !Command_wait(&cmd, true))
- return false;
+ !Command_wait(&cmd, true) ||
+ cmd.rc!=0)
+ result = false;
Command_free(&cmd);
- return true;
+ return result;
}
static bool
char const * bcast;
bool rc = false;
+ // skip 'disabled' interfaces
+ if (readEntryFlag(cfgdir, "disabled", false)) return true;
+
ip = readEntryStr (cfgdir, "ip", 0);
mask = readEntryStr (cfgdir, "mask", 0);
prefix = readEntryStr (cfgdir, "prefix", 0);
#include "vserver-start.h"
#include "configuration.h"
+#include "undo.h"
#include <lib_internal/util.h>
+static void
+Iface_removeWrapper(void const *iface)
+{
+ (void)Iface_remove(iface);
+}
+
void
activateInterfaces()
{
for (iface=Vector_begin(&cfg.interfaces);
iface!=Vector_end(&cfg.interfaces);
- ++iface)
- Iface_add(iface);
+ ++iface) {
+ if (!Iface_add(iface)) {
+ WRITE_MSG(2, "Failed to add interface ");
+ Iface_print(iface, 2);
+ WRITE_MSG(2, "\n");
+
+ exit(1);
+ }
+ Undo_addTask(Iface_removeWrapper, iface);
+ }
}
struct Interface const *dflt);
bool Iface_add(struct Interface const *);
bool Iface_del(struct Interface const *);
+bool Iface_remove(struct Interface const *);
+void Iface_print(struct Interface const *, int fd);
#include "interface-init.hc"
#include "interface-free.hc"
#include "pathconfig.h"
#include "interface.h"
#include "configuration.h"
+#include "mount.h"
+#include "undo.h"
#include "lib_internal/util.h"
#include "lib_internal/errinfo.h"
+#include "lib_internal/sys_clone.h"
#include "lib/vserver.h"
+#include "lib/internal.h"
#include <sys/file.h>
+#include <sched.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_SOCKET 1
+#define ENSC_WRAPPERS_FCNTL 1
+#define ENSC_WRAPPERS_STDLIB 1
+#include <ensc_wrappers/wrappers.h>
struct Options opts;
struct Configuration cfg;
initLock();
checkConstraints();
+ int sync_fd[2];
+ char c;
+ xid_t xid;
+ char buf[sizeof(xid)*3 + 2];
PathInfo cfgdir = { .d = opts.VSERVER_DIR, .l = strlen(opts.VSERVER_DIR) };
+ Esocketpair(AF_UNIX, SOCK_STREAM, 0, sync_fd);
+ Efcntl(sync_fd[0], F_SETFD, FD_CLOEXEC);
+ Efcntl(sync_fd[1], F_SETFD, FD_CLOEXEC);
+
getConfiguration(&cfg, &cfgdir);
- execScriptlets(&cfgdir, opts.VSERVER_NAME, "prepre-start");
- activateInterfaces();
+ pid_t pid = sys_clone(CLONE_NEWNS|SIGCHLD, 0);
+ FatalErrnoError(pid==-1, "sys_clone()");
+
+ switch (pid) {
+ case 0 :
+ Undo_init();
+ execScriptlets(&cfgdir, opts.VSERVER_NAME, "prepre-start");
+ activateInterfaces();
+
+ xid = Evc_ctx_create(cfg.xid);
+ mountVserver(&cfg);
+ // prepareInit(&cfg, &cfgdir);
+
+ Esend(sync_fd[0], &xid, sizeof xid, MSG_NOSIGNAL);
+ Erecv(sync_fd[0], &c, 1, 0);
+ execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start");
+
+ Undo_detach();
+ break;
+
+ default :
+ Erecv(sync_fd[1], &xid, sizeof xid, 0);
+ utilvserver_fmt_uint(buf, xid);
+ Esetenv("CHILD_XID", buf, 1);
+
+ execScriptlets(&cfgdir, opts.VSERVER_NAME, "pre-start.parent");
+ Esend(sync_fd[1], ".", 1, MSG_NOSIGNAL);
+
+ break;
+ }
}
"!!!LEGACY ALERT!!!\n"
"The special handling of non-executable scriptlets which allows to\n"
"override environment variables is not supported anymore. This change\n"
- "was needed as 'vserver ... start' is a done by a native C program\n"
- "now. If you need the old functionality please fill a bugreport so\n"
- "that workarounds can be found/implemented.\n"
+ "was needed as 'vserver ... start' is done by a native C program now.\n"
+ "If you need the old functionality please fill a bugreport so that\n"
+ "workarounds can be found/implemented.\n"
"The file triggering this message was\n"
" '");
WRITE_STR(2, fname);
return false;
}
- Command_init(&cmd, 4);
- Command_appendParameter(&cmd, fname);
- Command_appendParameter(&cmd, style);
- Command_appendParameter(&cmd, vname);
+ char const *par[] = { fname, style, vname, 0 };
+ Command_setParams(&cmd, par);
if (!Command_exec(&cmd, true) ||
!Command_wait(&cmd, true)) {
void
Vshelper_doSanityCheck()
{
- struct Command cmd = {
- .filename = "/bin/bash"
+ struct Command cmd;
+ char const * argv[] = {
+ "/bin/bash", "-c",
+ ". " PATH_UTILVSERVER_VARS ";. " PATH_FUNCTIONS "; vshelper.doSanityCheck",
+ 0
};
- Command_init(&cmd, 10);
- Command_appendParameter(&cmd, "/bin/bash");
- Command_appendParameter(&cmd, "-c");
- Command_appendParameter(&cmd, ". " PATH_UTILVSERVER_VARS ";. " PATH_FUNCTIONS "; vshelper.doSanityCheck");
+ Command_init(&cmd);
+ Command_setParams(&cmd, argv);
if (!Command_exec(&cmd, true) ||
!Command_wait(&cmd, true))
WRITE_MSG(2, "vserver-start: failed to do the vshelper-sanitycheck\n");