base @PKGLIBDIR@/capchroot
base @PKGLIBDIR@/chain-echo
core @PKGLIBDIR@/chcontext-compat
+core @PKGLIBDIR@/chbind-compat
base @PKGLIBDIR@/check-unixfile
base @PKGLIBDIR@/chroot-sh
base @PKGLIBDIR@/exec-ulimit
core @SBINDIR@/chxid
base @SBINDIR@/exec-cd
core @SBINDIR@/lsxid
+core @SBINDIR@/naddress
+core @SBINDIR@/nattribute
+core @SBINDIR@/ncontext
core @SBINDIR@/reducecap
core @SBINDIR@/setattr
core @SBINDIR@/showattr
return res;
}
+inline static WRAPPER_DECL nid_t
+Evc_get_task_nid(pid_t pid)
+{
+ register nid_t res = vc_get_task_nid(pid);
+ FatalErrnoError(res==VC_NOCTX, "vc_get_task_nid()");
+ return res;
+}
+
inline static WRAPPER_DECL xid_t
Evc_ctx_create(xid_t xid)
{
return res;
}
+inline static WRAPPER_DECL nid_t
+Evc_net_create(nid_t nid)
+{
+ register nid_t res = vc_net_create(nid);
+ FatalErrnoError(res==VC_NOCTX, "vc_net_create()");
+ return res;
+}
+
inline static WRAPPER_DECL void
Evc_ctx_migrate(xid_t xid)
{
}
inline static WRAPPER_DECL void
+Evc_net_migrate(nid_t nid)
+{
+ FatalErrnoError(vc_net_migrate(nid)==-1, "vc_net_migrate()");
+}
+
+inline static WRAPPER_DECL void
Evc_get_cflags(xid_t xid, struct vc_ctx_flags *flags)
{
FatalErrnoError(vc_get_cflags(xid, flags)==-1, "vc_get_cflags()");
}
inline static WRAPPER_DECL void
+Evc_get_nflags(nid_t nid, struct vc_net_flags *flags)
+{
+ FatalErrnoError(vc_get_nflags(nid, flags)==-1, "vc_get_nflags()");
+}
+
+inline static WRAPPER_DECL void
+Evc_set_nflags(nid_t nid, struct vc_net_flags const *flags)
+{
+ FatalErrnoError(vc_set_nflags(nid, flags)==-1, "vc_set_nflags()");
+}
+
+inline static WRAPPER_DECL void
Evc_set_vhi_name(xid_t xid, vc_uts_type type,
char const *val, size_t len)
{
}
inline static WRAPPER_DECL void
+Evc_get_ncaps(nid_t nid, struct vc_net_caps *caps)
+{
+ FatalErrnoError(vc_get_ncaps(nid, caps)==-1, "vc_get_ncaps()");
+}
+
+inline static WRAPPER_DECL void
+Evc_set_ncaps(nid_t nid, struct vc_net_caps const *caps)
+{
+ FatalErrnoError(vc_set_ncaps(nid, caps)==-1, "vc_set_ncaps()");
+}
+
+inline static WRAPPER_DECL void
Evc_set_namespace()
{
FatalErrnoError(vc_set_namespace()==-1, "vc_set_namespace()");
return rc;
}
+
+inline static WRAPPER_DECL nid_t
+Evc_nidopt2nid(char const *id, bool honor_static)
+{
+ char const * err;
+ nid_t rc = vc_nidopt2nid(id, honor_static, &err);
+ if (__builtin_expect(rc==VC_NOCTX,0)) {
+ ENSC_DETAIL1(msg, "vc_nidopt2nid", id, 1);
+ FatalErrnoErrorFail(msg);
+ }
+ return rc;
+}
lib/getvserverctx.c \
lib/getvservername.c \
lib/getvservervdir.c \
- lib/xidopt2xid.c
+ lib/xidopt2xid.c \
+ lib/nidopt2nid.c
lib_v11_SRCS = lib/syscall_rlimit.c \
lib/syscall_rlimit-v11.hc \
lib/syscall_kill.c \
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include <string.h>
+#include <stdlib.h>
+
+nid_t
+vc_nidopt2nid(char const *str, bool honor_static, char const **err_info)
+{
+ char const * err;
+ nid_t res = VC_NOCTX;
+
+ err = "vc_get_task_nid()";
+ if (strcmp(str,"self")==0) res = vc_get_task_nid(0);
+ else res = vc_xidopt2xid(str, honor_static, &err);
+
+ if (res==VC_NOCTX && err_info) *err_info = err;
+
+ return res;
+}
/** Maps an xid given at '--xid' options to an xid_t */
xid_t vc_xidopt2xid(char const *, bool honor_static, char const **err_info);
+ /** Maps a nid given at '--nid' options to a nid_t */
+ nid_t vc_nidopt2nid(char const *, bool honor_static, char const **err_info);
vcCfgStyle vc_getVserverCfgStyle(char const *id);
scripts_legacy_gen_SCRPTS = scripts/legacy/vps
scripts_legacy_src_PRGS = scripts/legacy/vserver-copy
-scripts_sbin_src_PRGS = scripts/chcontext \
+scripts_sbin_src_PRGS = scripts/chbind \
+ scripts/chcontext \
scripts/vapt-get \
scripts/vdispatch-conf \
scripts/vemerge \
--- /dev/null
+#! /bin/bash
+# $Id$
+
+# Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# Copyright (C) 2006 Daniel Hokka Zakrisson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+: ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+ echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
+ exit 1
+}
+. "$UTIL_VSERVER_VARS"
+. "$_LIB_FUNCTIONS"
+
+function showHelp()
+{
+ echo \
+$"Usage: $1 [--silent] [--nid <nid>] [--ip <ip_num>[/<mask>]]
+ [--bcast <broadcast>] [--] <commands> <args>*
+
+--silent
+ Do not print the addresses assigned.
+--nid <nid>
+ Network context id to use.
+--ip <ip_num>[/<mask>]
+ IP address to bind to.
+--bcast <broadcast>
+ Broadcast address for the network context.
+
+Report bugs to <$PACKAGE_BUGREPORT>."
+ exit $2
+}
+
+function showVersion()
+{
+ echo \
+$"chbind $PACKAGE_VERSION -- bind to IP addresses and execute a program
+This program is part of $PACKAGE_STRING
+
+Copyright (C) 2004 Enrico Scholz
+Copyright (C) 2006 Daniel Hokka Zakrisson
+This program is free software; you may redistribute it under the terms of
+the GNU General Public License. This program has absolutely no warranty."
+ exit $1
+}
+
+$_VSERVER_INFO - FEATURE vnet || exec $_CHBIND_COMPAT "$@"
+
+tmp=$(getopt -o + --long ncap:,nid:,ip:,bcast:,disconnect,flag:,secure,silent,help,version -n "$0" -- "$@") || exit 1
+eval set -- "$tmp"
+
+OPT_CAPS=()
+OPT_NID=
+OPT_DISCONNECT=
+OPT_FLAGS=()
+OPT_SECURE=
+OPT_SILENT=
+OPT_BCAST=
+OPT_IPS=()
+
+while true; do
+ case "$1" in
+ --help) showHelp $0 0;;
+ --version) showVersion 0;;
+ --ncap) OPT_CAPS=( "${OPT_CAPS[@]}" "$2" ); shift;;
+ --nid) OPT_NID=$2; shift;;
+ --disconnect) OPT_DISCONNECT=1;;
+ --flag) OPT_FLAGS=( "${OPT_FLAGS[@]}" "$2" ); shift;;
+ --secure) OPT_SECURE=1;;
+ --silent) OPT_SILENT=1;;
+ --ip) OPT_IPS=( "${OPT_IPS[@]}" "$2" ); shift;;
+ --bcast) OPT_BCAST=$2; shift;;
+ --) shift; break;;
+ *) echo $"chbind: internal error; arg=='$1'" >&2; exit 1;;
+ esac
+ shift
+done
+
+create_cmd=( $_NCONTEXT --create --silentexist
+ ${OPT_SILENT:+--silent}
+ ${OPT_NID:+--nid "$OPT_NID"} )
+
+chain_cmd=()
+
+old_IFS=$IFS
+IFS=,$IFS
+
+chain_cmd=( "${chain_cmd[@]}"
+ --
+ $_NATTRIBUTE --set
+ ${OPT_SECURE:+--secure}
+ ${OPT_CAPS:+--ncap "${OPT_CAPS[*]}"}
+ ${OPT_FLAGS:+--flag "${OPT_FLAGS[*]}"}
+ --
+ $_NADDRESS --add
+ ${OPT_SILENT:+--silent}
+ ${OPT_BCAST:+--bcast "$OPT_BCAST"} )
+
+for ip in "${OPT_IPS[@]}"; do
+ chain_cmd=( "${chain_cmd[@]}" --ip "$ip" )
+done
+
+migrate_cmd=( $_NCONTEXT
+ ${OPT_SILENT:+--silent}
+ ${OPT_DISCONNECT:+--disconnect} )
+
+IFS=$old_IFS
+
+if test -z "$OPT_NID" || $_VSERVER_INFO -q "$OPT_NID" XIDTYPE static; then
+ "${create_cmd[@]}" "${chain_cmd[@]}" -- "$@"
+ rc=$?
+else
+ rc=254
+fi
+
+test "$rc" -ne 254 || exec "${migrate_cmd[@]}" --nid "$OPT_NID" --migrate -- "$@"
+exit $rc
_CAPCHROOT="$__PKGLIBDIR/capchroot"
_CHAINECHO="$__PKGLIBDIR/chain-echo"
_CHBIND="$__SBINDIR/chbind"
+_CHBIND_COMPAT="$__PKGLIBDIR/chbind-compat"
_CHCONTEXT="$__SBINDIR/chcontext"
_CHCONTEXT_COMPAT="$__PKGLIBDIR/chcontext-compat"
_CHECK_UNIXFILE="$__PKGLIBDIR/check-unixfile"
_LISTDEVIP="$__LEGACYDIR/listdevip"
_LOCKFILE="$__PKGLIBDIR/lockfile"
_MASK2PREFIX="$__PKGLIBDIR/mask2prefix"
+_NADDRESS="$__SBINDIR/naddress"
+_NATTRIBUTE="$__SBINDIR/nattribute"
+_NCONTEXT="$__SBINDIR/ncontext"
_PARSERPMDUMP="$__LEGACYDIR/parserpmdump"
_PKGMGMT="$__PKGLIBDIR/pkgmgmt"
_READLINK="$__PKGLIBDIR/readlink"
src/secure-mount \
src/save_ctxinfo \
src/mask2prefix \
- src/chbind \
+ src/chbind-compat \
src/exec-cd \
src/fakerunlevel \
src/keep-ctx-alive \
src/vserver-info \
src/vdlimit \
src/vdu \
- src/vwait
+ src/vwait \
+ src/ncontext \
+ src/nattribute \
+ src/naddress
if ENSC_CAN_BEECRYPT_WITH_DIETLIBC
DIETPROGS += src/vhashify
src/rpm-fake-resolver \
src/vshelper-sync \
src/sigexec \
+ src/chbind-compat \
$(src_pkglib_C99_X_PROGS) \
$(src_pkglib_CXX_X_PROGS)
pkglib_LTLIBRARIES += src/rpm-fake.la
-sbin_PROGRAMS += src/chbind \
- src/exec-cd \
+sbin_PROGRAMS += src/exec-cd \
src/lsxid \
src/chxid \
src/vps \
src/vserver-info \
src/vuname \
src/vwait \
+ src/ncontext \
+ src/nattribute \
+ src/naddress \
$(src_sbin_CXX_X_PROGS)
if ENSC_HAVE_C99_COMPILER
src_capchroot_LDADD = $(VSERVER_LDADDS)
src_capchroot_LDFLAGS = $(VSERVER_LDFLGS)
-src_chbind_SOURCES = src/chbind.c
-src_chbind_LDADD = $(VSERVER_LDADDS)
-src_chbind_LDFLAGS = $(VSERVER_LDFLGS)
+src_chbind_compat_SOURCES = src/chbind.c
+src_chbind_compat_LDADD = $(VSERVER_LDADDS)
+src_chbind_compat_LDFLAGS = $(VSERVER_LDFLGS)
src_chcontext_compat_SOURCES = src/chcontext.c
src_chcontext_compat_LDADD = $(VSERVER_LDADDS) $(LIBINTERNAL)
src_vwait_LDADD = $(VSERVER_LDADDS)
src_vwait_LDFLAGS = $(VSERVER_LDFLGS)
+src_ncontext_SOURCES = src/ncontext.c
+src_ncontext_LDADD = $(VSERVER_LDADDS) $(LIBINTERNAL)
+src_ncontext_LDFLAGS = $(VSERVER_LDFLGS)
+
+src_nattribute_SOURCES = src/nattribute.c
+src_nattribute_LDADD = $(VSERVER_LDADDS)
+src_nattribute_LDFLAGS = $(VSERVER_LDFLGS)
+
+src_naddress_SOURCES = src/naddress.c
+src_naddress_LDADD = $(VSERVER_LDADDS)
+src_naddress_LDFLAGS = $(VSERVER_LDFLGS)
+
EXTRA_PROGRAMS += $(src_sbin_CXX_PROGS) $(src_pkglib_CXX_PROGS)
TESTS_ENVIRONMENT += srctestsuitedir=$(top_builddir)/src/testsuite
case CMD_SILENT : is_silent = true; break;
case CMD_BCAST : readBcast(optarg, &bcast); break;
#if defined(VC_ENABLE_API_NET)
- case CMD_NID : nid = Evc_xidopt2xid(optarg,true); break;
+ case CMD_NID : nid = Evc_nidopt2nid(optarg,true); break;
#else
case CMD_NID : WRITE_MSG(2, "WARNING: --nid is not supported by this version\n"); break;
#endif
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
+// based on chbind.cc by Jacques Gelinas
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "vserver.h"
+#include "util.h"
+
+#include <lib/internal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define ENSC_WRAPPERS_PREFIX "naddress: "
+#define ENSC_WRAPPERS_IO 1
+#define ENSC_WRAPPERS_UNISTD 1
+#define ENSC_WRAPPERS_VSERVER 1
+#include "wrappers.h"
+
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
+
+#define CMD_SILENT 0x2000
+#define CMD_NID 0x2001
+#define CMD_ADD 0x2002
+#define CMD_REMOVE 0x2003
+#define CMD_IP 0x2010
+#define CMD_BCAST 0x2011
+
+int wrapper_exit_code = 255;
+
+
+static struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "silent", no_argument, 0, CMD_SILENT },
+ { "add", no_argument, 0, CMD_ADD },
+ { "remove", no_argument, 0, CMD_REMOVE },
+ { "nid", required_argument, 0, CMD_NID },
+ { "ip", required_argument, 0, CMD_IP },
+ { "bcast", required_argument, 0, CMD_BCAST },
+ { 0,0,0,0 }
+};
+
+struct vc_ips {
+ struct vc_net_nx a;
+ struct vc_ips *next;
+};
+
+struct Arguments {
+ nid_t nid;
+ struct vc_ips head;
+ bool is_silent;
+ bool do_add;
+ bool do_remove;
+};
+
+static void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage:\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [--silent] [--nid <nid>] [--ip <ip_num>[/<mask>]] [--bcast <broadcast>] [--] <commands> <args>*\n\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(res);
+}
+
+static void
+showVersion()
+{
+ WRITE_MSG(1,
+ "naddress " VERSION " -- bind to an ip and execute a program\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2003,2004 Enrico Scholz\n"
+ "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+/*
+ Check if a network device exist in /proc/net/dev.
+ This is used because ifconfig_ioctl triggers modprobe if requesting
+ information about non existant devices.
+
+ Return != 0 if the device exist.
+*/
+static bool
+existsDevice(char const *dev_raw)
+{
+ size_t buf_size=8192;
+ char dev[strlen(dev_raw)+2];
+
+ strcpy(dev, dev_raw);
+ strcat(dev, ":");
+ for (;;) {
+ char buf[buf_size];
+ char * pos;
+ bool too_small;
+ int fd=open("/proc/net/dev", O_RDONLY);
+
+ if (fd==-1) return false;
+ too_small = EreadAll(fd, buf, buf_size);
+ close(fd);
+
+ if (too_small) {
+ buf_size *= 2;
+ continue;
+ }
+
+ pos = strstr(buf, dev);
+ return (pos && (pos==buf || pos[-1]==' ' || pos[-1]=='\n'));
+ }
+}
+
+static int ifconfig_ioctl(
+ int fd,
+ const char *ifname,
+ int cmd,
+ struct ifreq *ifr)
+{
+ strcpy(ifr->ifr_name, ifname);
+ return ioctl(fd, cmd, ifr);
+}
+
+/*
+ Fetch the IP number of an interface from the kernel.
+ Assume the device is already available in the kernel
+ Return -1 if any error.
+*/
+int ifconfig_getaddr (
+ const char *ifname,
+ uint32_t *addr,
+ uint32_t *mask,
+ uint32_t *bcast)
+{
+ int ret = -1;
+ if (existsDevice(ifname)){
+ int skfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (skfd != -1){
+ struct ifreq ifr;
+ if (addr != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *addr = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ if (mask != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *mask = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ if (bcast != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *bcast = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ close (skfd);
+ }
+ }
+ return ret;
+}
+
+static int
+convertAddress(const char *str, vc_net_nx_type *type, void *dst)
+{
+ int ret;
+ if (type) *type = vcNET_IPV4;
+ ret = inet_pton(AF_INET, str, dst);
+ if (ret==0) {
+ if (type) *type = vcNET_IPV6;
+ ret = inet_pton(AF_INET6, str, dst);
+ }
+ return ret > 0 ? 0 : -1;
+}
+
+static void
+readIP(char const *str, struct vc_ips **ips)
+{
+ if (ifconfig_getaddr(str, &(*ips)->a.ip[0], &(*ips)->a.mask[0], NULL)==-1) {
+ char *pt;
+ char tmpopt[strlen(str)+1];
+ uint32_t *mask = (*ips)->a.mask;
+
+ strcpy(tmpopt,str);
+ pt = strchr(tmpopt,'/');
+ if (pt)
+ *pt++ = '\0';
+
+ if (convertAddress(tmpopt, &(*ips)->a.type, (*ips)->a.ip) == -1) {
+ WRITE_MSG(2, "Invalid IP number '");
+ WRITE_STR(2, tmpopt);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+
+ if (pt==0) {
+ switch ((*ips)->a.type) {
+ case vcNET_IPV4:
+ mask[0] = htonl(0xffffff00);
+ break;
+ case vcNET_IPV6:
+ mask[0] = 64;
+ break;
+ default: break;
+ }
+ }
+ else {
+ // Ok, we have a network size, not a netmask
+ if (strchr(pt,'.')==0 && strchr(pt,':')==0) {
+ int sz = atoi(pt);
+ switch ((*ips)->a.type) {
+ case vcNET_IPV4:
+ mask[0] = htonl((1 << sz) - 1);
+ break;
+ case vcNET_IPV6:
+ mask[0] = sz;
+ break;
+ default: break;
+ }
+ }
+ else {
+ if (convertAddress(pt, NULL, &(*ips)->a.mask) == -1) {
+ WRITE_MSG(2, "Invalid netmask '");
+ WRITE_STR(2, pt);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+ }
+ }
+ }
+ else
+ (*ips)->a.type = vcNET_IPV4;
+
+ (*ips)->a.count = 1;
+ (*ips)->next = calloc(1, sizeof(struct vc_ips));
+ *ips = (*ips)->next;
+}
+
+static void
+readBcast(char const *str, struct vc_ips **ips)
+{
+ uint32_t bcast;
+ if (ifconfig_getaddr(str, NULL, NULL, &bcast)==-1){
+ if (convertAddress(str, NULL, &bcast) == -1) {
+ WRITE_MSG(2, "Invalid broadcast number '");
+ WRITE_STR(2, optarg);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+ }
+ (*ips)->a.ip[0] = bcast;
+ (*ips)->a.count = 1;
+ (*ips)->a.type = vcNET_IPV4B;
+ (*ips)->next = calloc(1, sizeof(struct vc_ips));
+ *ips = (*ips)->next;
+}
+
+static void
+tellAddress(struct vc_net_nx *addr, bool silent)
+{
+ char buf[41];
+ if (silent)
+ return;
+ if (inet_ntop(addr->type == vcNET_IPV6 ? AF_INET6 : AF_INET,
+ &addr->ip, buf, sizeof(buf)) == NULL) {
+ WRITE_MSG(1, " <conversion failed>");
+ return;
+ }
+ WRITE_MSG(1, " ");
+ WRITE_STR(1, buf);
+}
+
+static inline void
+doit(struct Arguments *args)
+{
+ struct vc_ips *ips;
+ if (args->do_add) {
+ if (!args->is_silent)
+ WRITE_MSG(1, "Adding");
+ for (ips = &args->head; ips->next; ips = ips->next) {
+ tellAddress(&ips->a, args->is_silent);
+ if (vc_net_add(args->nid, &ips->a) != (int)ips->a.count) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_net_add()");
+ exit(wrapper_exit_code);
+ }
+ }
+ if (!args->is_silent)
+ WRITE_MSG(1, "\n");
+ }
+ else if (args->do_remove) {
+ if (!args->is_silent)
+ WRITE_MSG(1, "Removing");
+ for (ips = &args->head; ips->next; ips = ips->next) {
+ tellAddress(&ips->a, args->is_silent);
+ if (vc_net_remove(args->nid, &ips->a) != (int)ips->a.count) {
+ perror(ENSC_WRAPPERS_PREFIX "vc_net_remove()");
+ exit(wrapper_exit_code);
+ }
+ }
+ if (!args->is_silent)
+ WRITE_MSG(1, "\n");
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ struct Arguments args = {
+ .nid = VC_NOCTX,
+ .is_silent = false,
+ .do_add = false,
+ .do_remove = false,
+ .head = { .next = NULL },
+ };
+ struct vc_ips *ips = &args.head;
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_SILENT : args.is_silent = true; break;
+ case CMD_BCAST : readBcast(optarg, &ips); break;
+ case CMD_NID : args.nid = Evc_nidopt2nid(optarg,true); break;
+ case CMD_ADD : args.do_add = true; break;
+ case CMD_REMOVE : args.do_remove = true; break;
+ case CMD_IP : readIP(optarg, &ips); break;
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help\" for more information.\n");
+ exit(wrapper_exit_code);
+ break;
+ }
+ }
+
+ if (args.nid == VC_NOCTX) args.nid = Evc_get_task_nid(0);
+
+ if (!args.do_add && !args.do_remove) {
+ WRITE_MSG(2, "No operation specified; try '--help' for more information\n");
+ exit(wrapper_exit_code);
+ }
+ else if (args.do_add && args.do_remove) {
+ WRITE_MSG(2, "Multiple operations specified; try '--help' for more information\n");
+ exit(wrapper_exit_code);
+ }
+
+ doit(&args);
+
+ if (optind != argc)
+ Eexecvp (argv[optind],argv+optind);
+ return EXIT_SUCCESS;
+}
+
+#ifdef ENSC_TESTSUITE
+#include <assert.h>
+
+void test()
+{
+ struct vc_ip_mask_pair ip;
+ uint32_t bcast;
+
+ bcast = 0;
+ readIP("1.2.3.4", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffffff00) && bcast==0);
+
+ readIP("1.2.3.4/8", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xff000000) && bcast==0);
+
+ readIP("1.2.3.4/255.255.0.0", &ip, &bcast);
+ assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffff0000) && bcast==0);
+
+ readIP("localhost", &ip, &bcast);
+ assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xffffff00) && bcast==0);
+
+#if 0
+ if (ifconfig_getaddr("lo", &tmp, &tmp, &tmp)!=-1) {
+ readIP("lo", &ip, &bcast);
+ assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xff000000) && bcast==ntohl(0x7fffffff));
+ }
+#endif
+}
+#endif
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// Copyright (C) 2006 Daniel Hokka Zakrisson
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "util.h"
+#include <lib/vserver.h>
+
+#include <getopt.h>
+#include <stdint.h>
+#include <errno.h>
+
+#define ENSC_WRAPPERS_PREFIX "nattribute: "
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include <wrappers.h>
+
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
+#define CMD_NID 0x2000
+#define CMD_SET 0x2001
+#define CMD_CAP 0x2002
+#define CMD_FLAG 0x2003
+#define CMD_SECURE 0x2004
+
+int wrapper_exit_code = 1;
+
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "nid", required_argument, 0, CMD_NID },
+ { "set", no_argument, 0, CMD_SET },
+ { "ncap", required_argument, 0, CMD_CAP },
+ { "flag", required_argument, 0, CMD_FLAG },
+ { "secure", no_argument, 0, CMD_SECURE },
+ {0,0,0,0}
+};
+
+struct Arguments {
+ nid_t nid;
+ struct vc_net_flags flags;
+ struct vc_net_caps caps;
+};
+
+static void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage:\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " --set [--nid <nid>] [--ncap [~!]<ncap>] [--flag [~!]<flag>] [--secure] -- [<program> <args>*]\n"
+ "\n"
+ " --ncap <cap> ... network capability to be added\n"
+ " --flag <flag> ... network flag to be added\n"
+ "\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(res);
+}
+
+static void
+showVersion()
+{
+ WRITE_MSG(1,
+ "nattribute " VERSION " -- sets attributes of network contexts\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2004 Enrico Scholz\n"
+ "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+static void
+parseFlags(char const *str, struct vc_net_flags *flags)
+{
+ struct vc_err_listparser err;
+ int rc;
+
+ rc = vc_list2nflag(str, 0, &err, flags);
+
+ if (rc==-1) {
+ WRITE_MSG(2, "Unknown flag '");
+ Vwrite(2, err.ptr, err.len);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+}
+
+static void
+parseNCaps(char const *str, struct vc_net_caps *caps)
+{
+ struct vc_err_listparser err;
+ int rc;
+
+ rc = vc_list2ncap(str,0, &err, caps);
+
+ if (rc==-1) {
+ WRITE_MSG(2, "Unknown ncap '");
+ Vwrite(2, err.ptr, err.len);
+ WRITE_MSG(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+}
+
+static void
+parseSecure(struct vc_net_flags * flags,
+ struct vc_net_caps * caps)
+{
+ // TODO: generalize this
+ caps->ncaps = 0ull;
+ caps->cmask = 0ull;
+
+ flags->flagword = 0ull;
+ flags->mask = 0ull;
+}
+
+int main(int argc, char *argv[])
+{
+ struct Arguments args = {
+ .nid = VC_NOCTX,
+ .flags = { .flagword = 0, .mask = 0 },
+ .caps = { .ncaps = 0, .cmask = 0 },
+ };
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_SET : break; // default op currently
+ case CMD_NID : args.nid = Evc_nidopt2nid(optarg,true); break;
+ case CMD_FLAG : parseFlags(optarg, &args.flags); break;
+ case CMD_CAP : parseNCaps(optarg, &args.caps); break;
+ case CMD_SECURE : parseSecure(&args.flags, &args.caps); break;
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help\" for more information.\n");
+ return 255;
+ break;
+ }
+ }
+
+ if (args.nid==VC_NOCTX) args.nid = Evc_get_task_nid(0);
+
+ if (args.caps.cmask &&
+ vc_set_ncaps(args.nid, &args.caps)==-1)
+ perror(ENSC_WRAPPERS_PREFIX "vc_set_ncaps()");
+ else if (args.flags.mask &&
+ vc_set_nflags(args.nid, &args.flags)==-1)
+ perror(ENSC_WRAPPERS_PREFIX "vc_set_nflags()");
+ else if (optind<argc)
+ EexecvpD(argv[optind], argv+optind);
+ else
+ return EXIT_SUCCESS;
+
+ return EXIT_FAILURE;
+}
--- /dev/null
+// $Id$ --*- c -*--
+
+// Copyright (C) 2004-2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "util.h"
+#include "lib/internal.h"
+#include "lib_internal/util.h"
+#include "lib_internal/jail.h"
+
+#include <vserver.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <signal.h>
+#include <sys/types.h>
+
+
+#define ENSC_WRAPPERS_PREFIX "ncontext: "
+#define ENSC_WRAPPERS_UNISTD 1
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_FCNTL 1
+#define ENSC_WRAPPERS_SOCKET 1
+#define ENSC_WRAPPERS_IOSOCK 1
+#include <wrappers.h>
+
+#define CMD_HELP 0x1000
+#define CMD_VERSION 0x1001
+#define CMD_NID 0x4000
+#define CMD_CREATE 0x4001
+#define CMD_MIGRATE 0x4002
+#define CMD_DISCONNECT 0x4003
+#define CMD_SILENT 0x4004
+#define CMD_SYNCSOCK 0x4005
+#define CMD_SYNCMSG 0x4006
+#define CMD_MIGRATESELF 0x4007
+#define CMD_SILENTEXIST 0x4008
+
+
+struct option const
+CMDLINE_OPTIONS[] = {
+ { "help", no_argument, 0, CMD_HELP },
+ { "version", no_argument, 0, CMD_VERSION },
+ { "nid", required_argument, 0, CMD_NID },
+ { "create", no_argument, 0, CMD_CREATE },
+ { "migrate", no_argument, 0, CMD_MIGRATE },
+ { "migrate-self", no_argument, 0, CMD_MIGRATESELF },
+ { "disconnect", no_argument, 0, CMD_DISCONNECT },
+ { "silent", no_argument, 0, CMD_SILENT },
+ { "silentexist", no_argument, 0, CMD_SILENTEXIST },
+ { "syncsock", required_argument, 0, CMD_SYNCSOCK },
+ { "syncmsg", required_argument, 0, CMD_SYNCMSG },
+ { 0,0,0,0 },
+};
+
+struct Arguments {
+ bool do_create;
+ bool do_migrate;
+ bool do_migrateself;
+ bool do_disconnect;
+ bool is_silentexist;
+ int verbosity;
+ nid_t nid;
+ char const * sync_sock;
+ char const * sync_msg;
+};
+
+int wrapper_exit_code = 255;
+
+static void
+showHelp(int fd, char const *cmd, int res)
+{
+ WRITE_MSG(fd, "Usage:\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " --create [--nid <nid>] <opts>* [--] <program> <args>*\n ");
+ WRITE_STR(fd, cmd);
+ WRITE_MSG(fd,
+ " [(--migrate --nid <nid>)|--migrate-self] <opts>* [--] <program> <args>*\n"
+ "\n"
+ "<opts> can be:\n"
+ " --disconnect ... start program in background\n"
+ " --silent ... be silent\n"
+ " --silentexist ... be silent when context exists already; useful\n"
+ " for '--create' only\n"
+ " --syncsock <filename>\n"
+ " ... before executing the program, send a message\n"
+ " to the socket and wait until it closes.\n"
+ " <filename> must be a SOCK_STREAM unix socket\n"
+ " --syncmsg <message>\n"
+ " ... use <message> as synchronization message; by\n"
+ " default, 'ok' will be used\n"
+ "\n"
+ "'ncontext --create' exits with code 254 iff the context exists already.\n"
+ "\n"
+ "Please report bugs to " PACKAGE_BUGREPORT "\n");
+
+ exit(res);
+}
+
+static void
+showVersion()
+{
+ WRITE_MSG(1,
+ "ncontext " VERSION " -- manages the creation of network contexts\n"
+ "This program is part of " PACKAGE_STRING "\n\n"
+ "Copyright (C) 2004-2006 Enrico Scholz\n"
+ "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
+ VERSION_COPYRIGHT_DISCLAIMER);
+ exit(0);
+}
+
+#include "context-sync.hc"
+
+static inline ALWAYSINLINE void
+tellContext(nid_t nid, bool do_it)
+{
+ char buf[sizeof(nid_t)*3+2];
+ size_t l;
+
+ if (!do_it) return;
+
+ l = utilvserver_fmt_long(buf,nid);
+
+ WRITE_MSG(1, "New network context is ");
+ Vwrite (1, buf, l);
+ WRITE_MSG(1, "\n");
+}
+
+static int
+connectExternalSync(char const *filename)
+{
+ int fd;
+ struct sockaddr_un addr;
+
+ if (filename==0) return -1;
+
+ ENSC_INIT_UNIX_SOCK(addr, filename);
+
+ fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
+ Econnect(fd, &addr, sizeof(addr));
+
+ return fd;
+}
+
+static void
+doExternalSync(int fd, char const *msg)
+{
+ char c;
+
+ if (fd==-1) return;
+
+ if (msg) EsendAll(fd, msg, strlen(msg));
+ Eshutdown(fd, SHUT_WR);
+
+ if (TEMP_FAILURE_RETRY(recv(fd, &c, 1, MSG_NOSIGNAL))!=0) {
+ WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unexpected external synchronization event\n");
+ exit(wrapper_exit_code);
+ }
+
+ Eclose(fd);
+}
+
+static inline ALWAYSINLINE int
+doit(struct Arguments const *args, int argc, char *argv[])
+{
+ int p[2][2];
+ pid_t pid = initSync(p, args->do_disconnect);
+
+ if (pid==0) {
+ nid_t nid;
+ int ext_sync_fd = connectExternalSync(args->sync_sock);
+
+ doSyncStage0(p, args->do_disconnect);
+
+ if (args->do_create) {
+ nid = vc_net_create(args->nid);
+ if (nid==VC_NOCTX) {
+ switch (errno) {
+ case EEXIST :
+ if (!args->is_silentexist)
+ perror(ENSC_WRAPPERS_PREFIX "vc_net_create()");
+ return 254;
+ default :
+ perror(ENSC_WRAPPERS_PREFIX "vc_net_create()");
+ return wrapper_exit_code;
+ }
+ }
+ tellContext(nid, args->verbosity>=1);
+ }
+ else
+ nid = args->nid;
+
+ if (args->do_migrate && !args->do_migrateself)
+ Evc_net_migrate(nid);
+
+ doExternalSync(ext_sync_fd, args->sync_msg);
+ doSyncStage1(p, args->do_disconnect);
+ DPRINTF("doit: pid=%u, ppid=%u\n", getpid(), getppid());
+ execvp (argv[optind],argv+optind);
+ doSyncStage2(p, args->do_disconnect);
+
+ PERROR_Q(ENSC_WRAPPERS_PREFIX "execvp", argv[optind]);
+ exit(wrapper_exit_code);
+ }
+
+ assert(args->do_disconnect);
+
+ waitOnSync(pid, p, args->nid!=VC_DYNAMIC_XID && args->do_migrate);
+ return EXIT_SUCCESS;
+}
+
+int main (int argc, char *argv[])
+{
+ struct Arguments args = {
+ .nid = VC_DYNAMIC_XID,
+ .do_create = false,
+ .do_migrate = false,
+ .do_migrateself = false,
+ .do_disconnect = false,
+ .is_silentexist = false,
+ .verbosity = 1,
+ .sync_msg = "ok",
+ };
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_CREATE : args.do_create = true; break;
+ case CMD_MIGRATE : args.do_migrate = true; break;
+ case CMD_DISCONNECT : args.do_disconnect = true; break;
+ case CMD_SILENTEXIST : args.is_silentexist = true; break;
+ case CMD_SYNCSOCK : args.sync_sock = optarg; break;
+ case CMD_SYNCMSG : args.sync_msg = optarg; break;
+ case CMD_NID : args.nid = Evc_nidopt2nid(optarg,true); break;
+ case CMD_SILENT : --args.verbosity; break;
+ case CMD_MIGRATESELF :
+ args.do_migrate = true;
+ args.do_migrateself = true;
+ break;
+
+ default :
+ WRITE_MSG(2, "Try '");
+ WRITE_STR(2, argv[0]);
+ WRITE_MSG(2, " --help' for more information.\n");
+ return wrapper_exit_code;
+ break;
+ }
+ }
+
+ signal(SIGCHLD, SIG_DFL);
+
+ if (args.do_migrateself)
+ args.nid = Evc_get_task_nid(0);
+
+ if (!args.do_create && !args.do_migrate)
+ WRITE_MSG(2, "Neither '--create' nor '--migrate specified; try '--help' for more information\n");
+ else if (args.do_create && args.do_migrate)
+ WRITE_MSG(2, "Can not specify '--create' and '--migrate' at the same time; try '--help' for more information\n");
+ else if (!args.do_create && args.nid==VC_DYNAMIC_XID)
+ WRITE_MSG(2, "Can not migrate to an unknown context\n");
+ else if (optind>=argc)
+ WRITE_MSG(2, "No command given; use '--help' for more information.\n");
+ else
+ return doit(&args, argc, argv);
+
+ return wrapper_exit_code;
+}