Add basic support for creating tun/tap interfaces in the configuration.
authorDaniel Hokka Zakrisson <daniel@hozac.com>
Sat, 1 Mar 2008 00:22:34 +0000 (00:22 +0000)
committerDaniel Hokka Zakrisson <daniel@hozac.com>
Sat, 1 Mar 2008 00:22:34 +0000 (00:22 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2692 94cd875c-1c1d-0410-91d2-eb244daf1a30

doc/configuration.xml
scripts/util-vserver-vars.pathsubst
scripts/vserver.functions
scripts/vserver.stop
src/tunctl.c

index 75a7af9..9ce06f0 100644 (file)
@@ -1341,6 +1341,47 @@ When this file exists, the steps which setup and destroy a VLAN
 interface will be executed.
          </description>
        </boolean>
+       <boolean name="tun" since="0.30.215">
+         <description>
+When this file exists, a tun interface will be created when the guest
+starts, and removed when the guest stops.
+         </description>
+       </boolean>
+       <boolean name="tap" since="0.30.215">
+         <description>
+When this file exists, a tap interface will be created when the guest
+starts, and removed when the guest stops.
+         </description>
+       </boolean>
+       <boolean name="nocsum" since="0.30.215">
+         <description>
+If a tun or tap interface is created, the presence of this file will
+disable checksumming on it.
+         </description>
+       </boolean>
+       <boolean name="shared" since="0.30.215">
+         <description>
+When this file exists, the tun/tap interface created will not be
+owned by this particular guest.
+         </description>
+       </boolean>
+       <scalar name="uid" since="0.30.215">
+         <description>
+Sets the ownership of tun/tap interfaces. Requires a user id, not a
+username.
+         </description>
+       </scalar>
+       <scalar name="gid" since="0.30.215">
+         <description>
+Sets the group ownership of tun/tap interfaces. Requires a group id,
+not a group name.
+         </description>
+       </scalar>
+       <scalar name="linktype" since="0.30.215">
+         <description>
+Sets the link type of tun/tap interfaces.
+         </description>
+       </scalar>
       </collection>
     </collection>
     
index 00a7c42..fc50a56 100644 (file)
@@ -70,6 +70,7 @@ _SECURE_MOUNT="$__PKGLIBDIR/secure-mount"
 _SETATTR="$__SBINDIR/setattr"
 _SHOWPERM="$__LEGACYDIR/showperm"
 _START_VSERVERS="$__PKGLIBDIR/start-vservers"
+_TUNCTL="$__PKGLIBDIR/tunctl"
 _VAPT_GET="$__SBINDIR/vapt-get"
 _VAPT_GET_WORKER="$__PKGLIBDIR/vapt-get-worker"
 _VATTRIBUTE="$__SBINDIR/vattribute"
index e6482c6..472673a 100644 (file)
@@ -66,6 +66,7 @@ _IS_FAKEINIT=
 INITSTYLE=sysv
 
 S_CONTEXT=
+N_CONTEXT=
 
 SILENT_OPT=
 
@@ -108,9 +109,7 @@ function _generateChbindOptions
     f="$vdir"/interfaces/lback
     getFileValue lback "$f"
 
-    getFileValue nid "$vdir/ncontext" "$vdir/context"
-    
-    CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${nid:+--nid "$nid"}
+    CHBIND_CMD=( $_CHBIND $SILENT_OPT --secure ${N_CONTEXT:+--nid "$N_CONTEXT"}
                 ${bcast:+--bcast "$bcast"} ${lback:+--lback "$lback"}
                )
 
@@ -512,6 +511,33 @@ create them before starting the vserver and use the 'nodev' flag then"
     return 0
 }
 
+function _getTunInfo
+{
+    local iface="$1"
+
+    test -e "$iface/tun" -o -e "$iface/tap" || return 1
+    test ! -e "$iface/tun"     || echo --tun
+    test ! -e "$iface/tap"     || echo --tap
+    test ! -e "$iface/nocsum"  || echo --~checksum
+    test   -e "$iface/shared"  || echo --nid-failure-ok "$N_CONTEXT"
+    if test -e "$iface/uid"; then
+       local uid
+       getFileValue uid "$iface/uid"
+       echo --uid "$uid"
+    fi
+    if test -e "$iface/gid"; then
+       local gid
+       getFileValue gid "$iface/gid"
+       echo --gid "$gid"
+    fi
+    if test -e "$iface/linktype"; then
+       local linktype
+       getFileValue linktype "$iface/linktype"
+       echo --linktype "$linktype"
+    fi
+    return 0
+}
+
 ## Usage: _processSingleInterface <interface-directory>
 function _processSingleInterface
 {
@@ -571,21 +597,27 @@ function _processSingleInterface
 
        if ! test -e "$iface"/indirect; then
            # XXX: IPv6 hack
-           use_bcast="broadcast ${bcast:-+}"
+           local use_bcast="broadcast ${bcast:-+}"
            echo "$ip" | $_GREP -q : && use_bcast=
+
+           local tun_info
+           if tun_info=$(_getTunInfo "$iface"); then
+               _addInterfaceCmd TUNCTL "$dev" $tun_info
+           fi
+
            _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" $use_bcast ${name:+label "$dev:$name"} dev "$dev"
            #_addInterfaceCmd IP_ROUTE "$ip${prefix:+/$prefix}" dev "$dev"
            _addInterfaceCmd IP_LINK  "$dev" $up
-       elif ! test -n "$ctx"; then
+       elif ! test -n "$N_CONTEXT"; then
            echo $"Using 'dummy' (indirect) for interface '$dev' requires a fixed context number; dynamic ctx are not supported" >&2
            return 1
        else
-           test -z "$mac" || _generateMac mac "$(basename $iface)" "$ctx" || return 1
+           test -z "$mac" || _generateMac mac "$(basename $iface)" "$N_CONTEXT" || return 1
            _addInterfaceCmd MODPROBE dummy "$dev"
            _addInterfaceCmd IP_LINK  dev dummy0 address "$mac"
            _addInterfaceCmd NAMEIF   "$dev" "$mac"
            _addInterfaceCmd IP_ADDR  "$ip${prefix:+/$prefix}" dev "$dev"
-           test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$ctx" "$extip"
+           test -z "$extip" || _addInterfaceCmd IPTABLES "$ip${prefix:+/$prefix}" ${name:+label "$dev:$name"} "$N_CONTEXT" "$extip"
        fi
 
        break
@@ -596,9 +628,11 @@ function _processSingleInterface
 function _generateInterfaceOptions
 {
     local iface
-    local ctx
 
-    test ! -e "$1"/context || read ctx <"$1"/context
+    # XXX: This is here instead of in _generateChbindOptions
+    #      to avoid a circular dependency
+    getFileValue N_CONTEXT "$1/ncontext" "$1/context"
+    test -n "$N_CONTEXT" -o -z "$S_CONTEXT" || N_CONTEXT="$S_CONTEXT"
 
     for iface in "$1/interfaces/"*; do
         test   -d "$iface"          || continue
@@ -637,6 +671,11 @@ function enableInterfaces
            IP_ADDR_FLUSH)      $_IP addr  flush "$@";;
            IP_LINK)            $_IP link  set   "$@";;
            IP_ROUTE)           $_IP route add   "$@";;
+           TUNCTL)
+               local dev="$1"
+               shift
+               $_TUNCTL --persist "$@" "$dev"
+               ;;
            *)                  echo "Unknown interface-command type '$type'" >&2; false;;
        esac
 
@@ -672,6 +711,7 @@ function disableInterfaces
            IP_ADDR_FLUSH)      ;;
            IP_LINK)            ;; ## Ignore the link-down command for now
            IP_ROUTE)           $_IP route del "$@";;
+           TUNCTL)             $_TUNCTL --~persist "$1";;
            *)                  echo "Unknown interface-command type '$type'" >&2; false;;
        esac
     done
index 6b367dd..586adda 100644 (file)
@@ -95,9 +95,9 @@ fi
 
 # Remove persistent so those contexts can be stopped
 $_VATTRIBUTE --set --xid "$S_CONTEXT" --flag !persistent 2>/dev/null || :
-if $_VSERVER_INFO -q "$S_CONTEXT" XIDTYPE static &&
+if $_VSERVER_INFO -q "$N_CONTEXT" XIDTYPE static &&
    $_VSERVER_INFO - FEATURE vnet; then
-    $_NATTRIBUTE --set --nid "$S_CONTEXT" --flag !persistent 2>/dev/null || :
+    $_NATTRIBUTE --set --nid "$N_CONTEXT" --flag !persistent 2>/dev/null || :
 fi
 
 vshelper.doStopSync
index 6fe8a81..14b904a 100644 (file)
 #define CMD_LINKTYPE           0x0100
 #define CMD_TUN                        0x0200
 #define CMD_TAP                        0x0400
+#define CMD_NID_FAILURE_OK     (0x0800 | CMD_NID)
 
 int            wrapper_exit_code  =  255;
 
 struct option const
 CMDLINE_OPTIONS[] = {
-  { "help",       no_argument,       0, CMD_HELP },
-  { "version",    no_argument,       0, CMD_VERSION },
-  { "nid",        required_argument, 0, CMD_NID },
-  { "device",     required_argument, 0, CMD_DEVICE },
-  { "persist",    no_argument,       0, CMD_PERSIST },
-  { "~persist",   no_argument,       0, CMD_NOPERSIST },
-  { "checksum",   no_argument,       0, CMD_CSUM },
-  { "~checksum",  no_argument,       0, CMD_NOCSUM },
-  { "uid",        required_argument, 0, CMD_UID },
-  { "gid",        required_argument, 0, CMD_GID },
-  { "linktype",   required_argument, 0, CMD_LINKTYPE },
-  { "tun",        no_argument,       0, CMD_TUN },
-  { "tap",        no_argument,       0, CMD_TAP },
+  { "help",           no_argument,       0, CMD_HELP },
+  { "version",        no_argument,       0, CMD_VERSION },
+  { "nid",            required_argument, 0, CMD_NID },
+  { "device",         required_argument, 0, CMD_DEVICE },
+  { "persist",        no_argument,       0, CMD_PERSIST },
+  { "~persist",       no_argument,       0, CMD_NOPERSIST },
+  { "checksum",       no_argument,       0, CMD_CSUM },
+  { "~checksum",      no_argument,       0, CMD_NOCSUM },
+  { "uid",            required_argument, 0, CMD_UID },
+  { "gid",            required_argument, 0, CMD_GID },
+  { "linktype",       required_argument, 0, CMD_LINKTYPE },
+  { "tun",            no_argument,       0, CMD_TUN },
+  { "tap",            no_argument,       0, CMD_TAP },
+  { "nid-failure-ok", required_argument, 0, CMD_NID_FAILURE_OK },
   {0,0,0,0}
 };
 
@@ -140,8 +142,12 @@ doTunctl(struct Arguments *args, char *interface)
     EioctlD(fd, TUNSETOWNER, (void *) (long) args->uid);
   if (args->set & CMD_GID)
     EioctlD(fd, TUNSETGROUP, (void *) (long) args->gid);
-  if (args->set & CMD_NID)
-    EioctlD(fd, TUNSETNID, (void *) (long) args->nid);
+  if (args->set & CMD_NID) {
+    if (args->set & CMD_NID_FAILURE_OK)
+      ioctl(fd, TUNSETNID, (void *) (long) args->nid);
+    else
+      EioctlD(fd, TUNSETNID, (void *) (long) args->nid);
+  }
   if (args->set & CMD_LINKTYPE)
     EioctlD(fd, TUNSETLINK, (void *) (long) args->linktype);
   if (args->set & (CMD_PERSIST|CMD_NOPERSIST))
@@ -174,6 +180,7 @@ int main(int argc, char *argv[])
       case CMD_HELP    :  showHelp(1, argv[0], 0);
       case CMD_VERSION :  showVersion();
 
+      case CMD_NID_FAILURE_OK:
       case CMD_NID     :  args.nid = Evc_nidopt2nid(optarg, true);     break;
       case CMD_DEVICE  :  args.device = optarg;                        break;
       case CMD_PERSIST :  args.persist = 1;                            break;