Merge commit 'origin/0.7' into 0.7 0.7 0.7@12288 0.7@12817 trunk@12817
authorroot <root@blitz.inria.fr>
Fri, 2 Jul 2010 15:42:17 +0000 (17:42 +0200)
committerroot <root@blitz.inria.fr>
Fri, 2 Jul 2010 15:42:17 +0000 (17:42 +0200)
30 files changed:
Makefile
exec/dotsshmount [new file with mode: 0755]
exec/goodfences [new file with mode: 0755]
exec/if_port_forward [new file with mode: 0755]
exec/ipfw-be [new file with mode: 0755]
exec/mknod [new file with mode: 0755]
exec/reserve_tcp_port [new file with mode: 0755]
exec/reserve_udp_port [new file with mode: 0755]
exec/rsyncauthlogs [new file with mode: 0755]
exec/run_with_devices [new file with mode: 0644]
exec/setup-link
exec/setup-nat
exec/sliceip [new file with mode: 0755]
exec/umount [new file with mode: 0755]
exec/vif_down [new file with mode: 0755]
exec/vif_up [new file with mode: 0755]
fd_bmsocket.c [new file with mode: 0644]
fd_fusemount.c [new file with mode: 0644]
fd_tos.c [new file with mode: 0644]
fd_tuntap.c [new file with mode: 0644]
fd_udpsocket.c [new file with mode: 0644]
fdpass.c [new file with mode: 0644]
fdpass.h [new file with mode: 0644]
support/tun_test.c [new file with mode: 0644]
support/tunalloc.c [new file with mode: 0644]
support/tunalloc.h [new file with mode: 0644]
svn-commit.tmp [deleted file]
vsys-factory.spec [deleted file]
vsys-factory.spec.orig
vsys-scripts.spec [new file with mode: 0644]

index 8d4968d..bfea8db 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,28 @@
 CC=gcc
 CFLAGS=-g -O2
 
-all: dcookie
+all: dcookie fd_bmsocket fd_udpsocket fd_fusemount fd_tuntap fd_tos
+
+fd_tuntap: fd_tuntap.c
+       gcc fd_tuntap.c -o exec/fd_tuntap
 
 dcookie: dcookie.c
        gcc dcookie.c -o exec/dcookie
 
+fdpass.o: fdpass.c
+       gcc -c fdpass.c -o fdpass.o
+
+fd_bmsocket: fd_bmsocket.c fdpass.o
+       gcc fd_bmsocket.c fdpass.o -o exec/fd_bmsocket
+
+fd_udpsocket: fd_udpsocket.c fdpass.o
+       gcc fd_udpsocket.c fdpass.o -o exec/fd_udpsocket
+
+fd_fusemount: fd_fusemount.c fdpass.o
+       gcc fd_fusemount.c fdpass.o -o exec/fd_fusemount
+
+fd_tos: fd_tos.c fdpass.o
+       gcc fd_tos.c fdpass.o -o exec/fd_tos
+
 clean: 
        rm -f exec/*
diff --git a/exec/dotsshmount b/exec/dotsshmount
new file mode 100755 (executable)
index 0000000..9771556
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+SRC="/home/$1/.ssh/"
+DEST="/vservers/$1/home/$1/.ssh/"
+
+mkdir -p $DEST &> /dev/null
+
+mount | grep "on $DEST type" > /dev/null
+if [ $? -ne 0 ]; then
+   /bin/mount --bind -o ro $SRC $DEST > /dev/null
+fi
+
diff --git a/exec/goodfences b/exec/goodfences
new file mode 100755 (executable)
index 0000000..88c44e1
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+use strict;
+
+$|=1;
+
+my $slicename;
+my $portnumber;
+
+
+$slicename = $ARGV[0];
+$portnumber = <STDIN>;
+
+chop($portnumber);
+
+if ($portnumber!~/^\d+$/) {
+        die("$portnumber is not a port number");
+}
+
+open CMD,"/sbin/fuser -n tcp $portnumber 2>&1|";
+
+$_ = <CMD>;
+
+my @ports;
+@ports=split;
+
+if ($#ports > 0) {
+        system("cat /proc/$ports[1]/vinfo");
+        print "Please refer to http://planetflow.planet-lab.org/lookupslice.php to obtain the name corresponding to this slice.";
+}
+
+close CMD;
diff --git a/exec/if_port_forward b/exec/if_port_forward
new file mode 100755 (executable)
index 0000000..400591b
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+
+$|=1;
+$slice=$ARGV[0];
+$slice_ip=`cat /etc/vservers/$slice/interfaces/0/ip`;
+$src_port = <STDIN>;
+$dst_port = <STDIN>;
+
+chomp($slice_ip);
+chomp($src_port);
+chomp($dst_port);
+
+die ("Src and dst ports need to be numbers") if (($src_port=~/[^0-9]/) || ($src_port=~/[^0-9]/));
+
+$IPTABLES_CMD_1="/sbin/iptables -t nat -D PREROUTING -m tcp -p tcp -d $slice_ip --dport $src_port -j DNAT --to-destination $slice_ip:$dst_port";
+
+$IPTABLES_CMD_2="/sbin/iptables -t nat -A PREROUTING -m tcp -p tcp -d $slice_ip --dport $src_port -j DNAT --to-destination $slice_ip:$dst_port";
+
+print "Removing any previous instances of this rule: $IPTABLES_CMD_1\n";
+system($IPTABLES_CMD_1);
+
+print "Adding forwarding rule: $IPTABLES_CMD_2\n";
+system($IPTABLES_CMD_2);
+
+print "Done.\n";
diff --git a/exec/ipfw-be b/exec/ipfw-be
new file mode 100755 (executable)
index 0000000..b3b9439
--- /dev/null
@@ -0,0 +1,811 @@
+#!/bin/sh
+#
+# Marta Carbone, Luigi Rizzo
+# Copyright (C) 2009 Universita` di Pisa
+# $Id$
+#
+# This script the vsys backend used to configure emulation.
+# In detail it:
+# - reads the user's input from the vsys input pipe
+# - validates the input
+# - configures the firewall
+# - writes results on the output vsys pipe
+#
+# Configurable variables are at the beginning (only HOOK so far)
+
+# If HOOK is set, ${HOOK} is called before configuring a rule.
+# A sample hook can be found in the ipfwroot.rpm package,
+# it can be used to collect statistical information on dummynet usage.
+# To configure a hook, set the HOOK variable as follow:
+# HOOK=/tmp/sample_hook
+
+#--- You should not touch anything below this line. ----
+# For documentation see ARCHITECTURE near the end of the file.
+
+#--- global variables ---
+VERBOSE=0      # set to !0 to enable debug messages
+TEST=0         # set to 1 for test mode
+
+# The database and the lock file
+DBFILE=/tmp/ff
+lockfile=/var/lock/ipfw.lock
+
+# Min and max value (inclusive) for block_index
+BLOCK_MIN=1
+BLOCK_MAX=1000
+M=50           # size of per-slice block of rules
+# Min and max value (inclusive) for pipe_index
+PIPE_MIN=1
+PIPE_MAX=25000
+
+# These are the actual rule numbers used in ipfw
+IPFW_RULE_MIN=10000    # initial per-slice rule number
+IPFW_PIPE_MIN=10000    # initial pipe number
+
+# The skipto and the generic default rule
+# these values are used to initialize the firewall
+SLICE_TABLE=1          # table number used for slice ids lookup
+S=1000                 # firewall rule number for the skipto rule
+D=2000                 # default rule for reserved section
+
+# set slicename and slice_id
+# these are the credential of the user invoking the backend
+SLICENAME=$1
+SLICE_ID=`id -u $SLICENAME`
+[ x"$SLICE_ID" = x"" ] && echo "No sliver present." && exit
+
+# programs
+# XXX check consistency for variables {}
+SED=/bin/sed
+SEDOPT=-r
+[ -x ${SED} ] || { SED=`which sed` ; SEDOPT=-E ; }
+IPFW=/sbin/ipfw
+IPFW_CHECK="/sbin/ipfw -n"
+
+debug() { # $1 message to be displayed
+       [ x"${VERBOSE}" != x"0" ] && echo "ipfw-be: $1"
+}
+
+# if the first argument is -v, enable verbose mode
+set_verbose() {
+    [ x"$1" = x"-v" -o x"$2" = x"-v" ] && VERBOSE=1
+}
+
+# set test mode if -q is found
+set_test() {
+    [ x"$1" = x"-q" -o x"$2" = x"-q" ] || return
+    TEST=1
+    IPFW="/bin/echo ipfw:"
+    IPFW_CHECK="/bin/echo ipfw -n:"
+}
+
+abort() { # $1 message to be displayed in case of error
+       release_lock
+       echo "ipfw-be aborting (netconfig help): $1"
+       exit 1
+}
+
+# remove dangerous characters from user input
+# if present, the leading '-v/-q' will be removed
+filter() { # $* variables to be filtered
+       [ x${1} = x"-v" -o x${1} = x"-q" ] && shift
+       [ x${1} = x"-v" -o x${1} = x"-q" ] && shift
+       # allowed chars are: numbers, uppercase and lowercase letters,
+       # spaces, and the following symbols: .,_-/
+       echo "$*" | ${SED} ${SEDOPT} 's/[^\t0-9a-zA-Z., _\/\{}@-]*//g'
+}
+
+# remove all entries from the ipfw config, and create an empty db
+clean_db() {
+       rm -f ${DBFILE}
+       touch ${DBFILE}
+       # we would like to delete ranges of rules and pipes but this
+       # is not supported so for the time being we kill them all
+       ${IPFW} -q flush
+       ${IPFW} -q pipe flush
+       ${IPFW} -q table $SLICE_TABLE flush
+       #${IPFW} delete ${IPFW_RULE_MIN}-${IPFW_RULE_MAX}
+       #${IPFW} pipe delete ${IPFW_PIPE_MIN}-${IPFW_PIPE_MAX}
+       # since all rules are now deleted, we should initialize the firewall 
+       ipfw_init
+}
+
+#
+# Add the ipfw rule/pipe and update the database.
+# The pipe-in and pipe-out config are through global variables
+# rule_in rule_out because they may be long. XXX why ?
+# Other arguments are on the command line
+#
+# the new_rule variable is set if the rule to be installed is new
+# we need to know this because we do not want to clean
+# rule counters on pipes reconfiguration
+add_rule() { # slice_id new_rule type arg ipfw_rule pipe_index timeout
+    local slice_id=$1 new_rule=$2 type=$3 arg=$4
+    local ipfw_rule=$5 pipe_index=$6 timeout=$7
+    local ipfw_pipe_in ipfw_pipe_out check_timeout
+    local p h # used to split the argument
+
+    local h_in h_out
+    # local rule_in rule_out # XXX test if this works
+    # find actual pipe numbers
+    ipfw_pipe_in=$(($IPFW_PIPE_MIN + $((2 * $(($pipe_index - 1)))) ))
+    ipfw_pipe_out=$(($ipfw_pipe_in + 1))
+    local del          # used to delete incompatible configurations
+
+    # split the argument, and prepare PORTLIST (p) and ADDRLIST (h)
+    p=`echo $arg | cut -s -d "@" -f1-` # empty if no separator
+    if [ "$p" = "" ] ; then
+       p=$arg
+    else
+       p=`echo $arg | cut -d "@" -f1`
+       h=`echo $arg | cut -d "@" -f2`
+    fi
+
+    if [ "$h" = "" ] ; then
+       h_in=""
+       h_out=""
+    else
+       h_in=" src-ip ${h} "
+       h_out=" dst-ip ${h} "
+    fi
+
+    # first, call ipfw -n to check syntax, if ok move on and do the action
+    if [ x"$new_rule" != x"0" ] ; then
+       case $type in
+       SERVER|server)
+           rule_in="dst-port $p"
+           rule_out="src-port $p"
+           del=service
+           ;;
+       CLIENT|client)
+           rule_in="src-port $p"
+           rule_out="dst-port $p"
+           del=service
+           ;;
+       SERVICE|service)
+           rule_in="{ src-port $p or dst-port $p }"
+           rule_out="{ src-port $p or dst-port $p }"
+           del="cli_ser"
+           ;;
+       *)
+           abort "invalid service type $type"
+           ;;
+       esac
+
+       rule_in="pipe ${ipfw_pipe_in} in ${h_in} ${rule_in} // $type $arg $slice_id"
+       rule_out="pipe ${ipfw_pipe_out} out ${h_out} ${rule_out} // $type $arg $slice_id"
+
+       # Move into the user root directory. The profile should be located there
+       ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW_CHECK} add ${ipfw_rule} ${rule_in} ) > /dev/null || \
+               abort "ipfw syntax error ${rule_in}" 
+       ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW_CHECK} add ${ipfw_rule} ${rule_out} ) > /dev/null || \
+               abort "ipfw syntax error ${rule_out}" 
+    fi
+
+    # check error reporting
+    ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW_CHECK} pipe ${ipfw_pipe_in} config ${CONFIG_PIPE_IN} ) > /dev/null || \
+               abort "ipfw syntax error pipe_in" 
+    ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW_CHECK} pipe ${ipfw_pipe_out} config ${CONFIG_PIPE_OUT} ) > /dev/null || \
+               abort "ipfw syntax error pipe_out"
+
+    # all good, delete and add rules if necessary
+    [ "$del" = "service" ] && do_delete 0 $slice_id service $arg
+    [ "$del" = "cli_ser" ] && do_delete 0 $slice_id client $arg
+    [ "$del" = "cli_ser" ] && do_delete 0 $slice_id server $arg
+    [ "$new_rule" != "0" ] && ${IPFW} add ${ipfw_rule} $rule_in > /dev/null
+    [ "$new_rule" != "0" ] && ${IPFW} add ${ipfw_rule} $rule_out > /dev/null
+    # config pipes
+    ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW} pipe ${ipfw_pipe_in} config ${CONFIG_PIPE_IN} )
+    ( cd /vservers/${SLICENAME}/`pwd`/ ; ${IPFW} pipe ${ipfw_pipe_out} config ${CONFIG_PIPE_OUT} )
+
+    # send output to the user
+    ${IPFW} show ${ipfw_rule}
+    ${IPFW} pipe ${ipfw_pipe_in} show
+    ${IPFW} pipe ${ipfw_pipe_out} show
+
+    # do not write on the database on test-only
+    [ "$TEST" = "1" ] && return
+    # add to the database
+    ( grep -iv -- "^${slice_id} ${type} ${arg} " $DBFILE;  \
+       echo "${slice_id} ${type} ${arg} ${ipfw_rule} ${pipe_index} ${timeout}" ) > ${DBFILE}.tmp
+    mv ${DBFILE}.tmp ${DBFILE}
+}
+
+#
+# Delete a given configuration
+# if block_deletion !0 free block resources (if necessary)
+# otherwise leave the block allocated in case
+# we are adding the first rule
+do_delete() { # block_deletion slice_id type arg
+    local ipfw_pipe_in ipfw_pipe_out pipe_index ipfw_rule
+    local block_deletion=$1 slice_id=$2 type=$3 arg=$4
+
+    [ "${type}" = "BLOCK" ] && abort "A BLOCK can not be deleted"
+    [ "${arg}" = "" ] && abort "Missing args on 'delete', expected on of {CLIENT|SERVER|SERVICE} arg"
+    set `find_rule $slice_id $type $arg`
+    ipfw_rule=$1; pipe_index=$2
+    [ "$ipfw_rule" = "0" ] && return           # no rules found
+
+    # find actual pipe numbers XXX do as function
+    ipfw_pipe_in=$(($IPFW_PIPE_MIN + $((2 * $(($pipe_index - 1)))) ))
+    ipfw_pipe_out=$(($ipfw_pipe_in + 1))
+
+    echo "removing configuration ${slice_id} ${type} ${arg}"
+    [ "$TEST" = "1" ] && return 0
+    $IPFW delete ${ipfw_rule}
+    $IPFW pipe delete ${ipfw_pipe_in}
+    $IPFW pipe delete ${ipfw_pipe_out}
+    # remove from the database (case insensitive)
+    grep -iv -- "^${slice_id} ${type} ${arg} " $DBFILE > ${DBFILE}.tmp
+    mv ${DBFILE}.tmp ${DBFILE}
+
+    # if there are no more rules for the user
+    # remove the table entry from ipfw and from the db
+    [ $block_deletion = 0 ] && return 0
+
+    local rule_counter=`grep ^${slice_id} ${DBFILE} | wc -l`
+    [ $rule_counter -gt 1 ] && return 0        # there are still user rules
+    # delete the block and clean the table
+    local block_n=`grep "^${slice_id} BLOCK" ${DBFILE} | cut -d " " -f 3`
+    debug "Deleting BLOCK <${block_n}> entry from ipfw and from the database"
+    table_remove $slice_id $block_n 
+}
+
+# compare the argument with the first two field of
+# the database.
+# On match returns the block number, otherwise returns 0.
+# no echo inside
+find_block() { # $1 slice_id
+    local ret
+    ret=`grep -- "^$1 BLOCK " $DBFILE`
+
+    [ x"$ret" = x ] && echo "0" && return      # nothing found
+    # ignore multiple matches. If the db is corrupt we are
+    # screwed anyways
+    set $ret
+    echo "$3"
+}
+
+#
+# remove the default user rule and
+# the a BLOCK entry from ipfw and update the db
+# no echo inside
+table_remove() { # $slice_id $block_n
+    [ "$TEST" = "1" ] && return 0
+
+    # compute and delete the last user rule
+    local ipfw_rulemax=$(($IPFW_RULE_MIN + $(($M *${block_n})) -1))
+    ${IPFW} table $SLICE_TABLE delete $slice_id
+    ${IPFW} delete ${ipfw_rulemax}
+    ( grep -iv -- "^${slice_id} BLOCK ${block_n}" $DBFILE; ) > ${DBFILE}.tmp
+    mv ${DBFILE}.tmp ${DBFILE}
+    return 0
+}
+
+#
+# Find a rule and pipe_index for the given key (xid type arg)
+# Allocate a new block if first entry for this xid.
+# Rule and pipe are not written into the database, only the block is.
+#
+# Return ipfw_rule pipe_index new_rule
+# 'new_rule' is 0 if the rule existed, 1 if it is new
+#
+# return ipfw_rule = 0 if there are no resources available
+find_allocate() { # slice_id type arg
+    local slice_id=$1 type=$2 arg=$3
+    local ipfw_rule pipe_index new_block=0
+
+    # search for already allocated rule and pipes
+    set `find_rule $slice_id $type $arg`
+    ipfw_rule=$1; pipe_index=$2
+    [ ! ${ipfw_rule} = 0 ] && echo $ipfw_rule $pipe_index "0" && return 0      # rules found, return
+
+    # no rules found, search for an already existing block, or
+    # allocate a new one
+    local block_n=`find_block ${slice_id}`
+    [ ${block_n} = "0" ] && new_block=1 && block_n=`find_free_block`
+    [ ${block_n} = "0" -o ${block_n} -gt $BLOCK_MAX ] && echo 0 && return 0;
+
+    # We have a valid block, compute the range for user rules
+    local ipfw_rulemin=$(($IPFW_RULE_MIN + $(($M *$(($block_n - 1))))))
+    local ipfw_rulemax=$(($(($ipfw_rulemin + $M)) - 1 ))
+
+    # Find rule and pipes, reserve the last rule for the user's
+    # default rule that catches regular traffic.
+    set `allocate_resources $ipfw_rulemin $(($ipfw_rulemax - 1))`
+    ipfw_rule=$1; pipe_index=$2
+    [ $ipfw_rule = 0 ] && echo 0 && return 0   # no resources
+
+    # If this is a new block, add the slice to the lookup table
+    # and put a default rule at the end of the block.
+    if [ "$TEST" = "0" -a $new_block = 1 ] ; then
+       ${IPFW} table $SLICE_TABLE add ${slice_id} ${ipfw_rulemin} > /dev/null
+       ${IPFW} add ${ipfw_rulemax} allow all from any to any > /dev/null
+       ( echo "${slice_id} BLOCK ${block_n}" ) >> ${DBFILE}
+    fi
+
+    echo $ipfw_rule $pipe_index "1"
+    return 0
+}
+
+#
+# called with the database file as input
+# compare the tuple <slice_id type arg> with
+# the current firewall configuration. The database contains
+#      slice_id type arg ipfw_rule pipe_index timeout
+# On match returns <ipfw_rule pipe_index timeout>
+# On non match returns 0 0 0
+# no echo inside
+find_rule() { # slice_id type arg
+    local ret
+    ret=`grep -i -- "^$1 $2 $3 " $DBFILE | grep -v BLOCK`
+
+    [ x"$ret" = x ] && echo "0 0 0 " && return # nothing found
+    # ignore multiple matches. If the db is corrupt we are
+    # screwed anyways
+    set $ret
+    echo "$4 $5 $6"
+}
+
+#
+# Find a hole in a list of numbers within a range (boundaries included)
+# The input is passed as a sorted list of numbers on stdin.
+# Return a "0" rule if there is no rule free
+find_hole() {  # min max
+    local min=$1 cand=$1 max=$2 line
+    while read line ; do
+       [ $line -lt $min ] && continue
+        [ $line -ne $cand ] && break           # found
+       [ $cand -ge $max ] && cand=0 && break   # no space
+        cand=$(($cand + 1))
+    done
+    echo $cand
+}
+
+# XXX despite the name this does not allocate but only finds holes.
+# returns a free rule and pipe base for client|server|service
+# within a block
+# Returns r=0 if there are no resources available
+# no echo inside
+allocate_resources() { # ipfw_minrule ipfw_maxrule
+    local p r
+    # remove comments, extract field, sort
+    p=`grep -v '^#' $DBFILE | grep -v BLOCK | awk '{print $5}' | sort -n | \
+       find_hole $PIPE_MIN $PIPE_MAX`
+    r=`grep -v '^#' $DBFILE | grep -v BLOCK | awk '{print $4}' | sort -n | \
+       find_hole $1 $2`
+    [ $r = 0 -o $p = 0 ] && r=0                # no resources available
+    echo $r $p
+}
+
+
+# Returns the index of a free block
+# Returns 0 if there are no resources available
+# no debug inside
+find_free_block() {
+    b=`grep -v '^#' $DBFILE | grep BLOCK | awk '{print $3}' | sort -n | \
+       find_hole $BLOCK_MIN $BLOCK_MAX`
+    echo $b
+}
+
+# parse the ipfw database and remove expired rules
+#
+# Each timeout value stored in the database is compared against
+# the current time.  If the timeout is older than current,
+# the rules and related pipes will be deleted.
+kill_expired() { # slice_id type arg
+    local match timeout
+
+    # if there is no database file exit
+    [ ! -f ${DBFILE} ] && return 0
+
+    # Get the current time
+    now=`date -u +%s`
+
+    cp ${DBFILE} ${DBFILE}.kill
+    cat ${DBFILE}.kill | grep -v BLOCK |
+    while read line; do
+       match=`echo $line|cut -d " " -f 1-3`
+       timeout=`echo $line|cut -d " " -f 6`
+       [ $now -gt $timeout ] && do_delete 1 $match
+    done
+    rm ${DBFILE}.kill
+}
+
+# execute functions from root context
+# can be used from root context as follow:
+# echo "super $command $args" | /vsys/ipfw-be 0
+do_super() { # $arguments...
+       case $1 in
+       init)
+           ipfw_init; return 0
+           ;;
+       dbcleanup)
+           clean_db; return 0
+           ;;
+       killexpired)
+           kill_expired; return 0
+           ;;
+       *)
+           abort "Invalid super command"
+           ;;
+       esac
+}
+
+# refresh the rule timeout
+do_refresh() { # slice_id type arg timeout
+    local ipfw_pipe_in ipfw_pipe_out pipe_index 
+    local slice_id=$1 type=$2 arg=$3 timeout=$4
+
+    debug "do_refresh type: <$type> arg: <$arg> timeout: <$timeout>"
+    [ "${type}" = "BLOCK" ] && abort "BLOCK rule not valid"
+    [ "${timeout}" = "" ] && abort "Missing args on 'refresh', expected on of {SERVICE|SERVER|CLIENT} port_number"
+    set `find_rule $slice_id $type $arg`
+    ipfw_rule=$1; pipe_index=$2
+    [ "${ipfw_rule}" = "0" ] && debug "no rules found" && return 0             # no rules found
+
+    [ "$TEST" = "1" ] && return
+    # update the database with the new timeout value
+    ( grep -iv -- "^${slice_id} ${type} ${arg} " $DBFILE;  \
+       echo "${slice_id} ${type} ${arg} ${ipfw_rule} ${pipe_index} ${timeout}" ) > ${DBFILE}.tmp
+    mv ${DBFILE}.tmp ${DBFILE}
+    echo "refreshed timeout for rule ${type} ${arg}"
+}
+
+# process a request.
+# A request is made by a set of arguments formatted as follow:
+#
+# config {server|client|service} arg [-t timeout] IN <pipe_conf> OUT <pipe_conf>
+# show {rules|pipes} [args]
+# delete type arg
+# refresh type arg [-t timeout]
+#
+# The timeout value is expressed as:
+# week, day, month or anything else accepted by the date command.
+# The id of the slice issuing the request is in the $SLICE_ID variable,
+# set at the beginning of this script.
+process() {
+    local new_pipe=0
+    local timeout TMP i rule_base pipe_base
+    local cmd=$1 ; shift
+    local debug_args="$*";
+    local type=$1 ; shift
+    local args="$*"
+    debug "Received command: <$cmd> arguments: <$debug_args>"
+
+    # set the timeout value
+    # if present, extract the '-t timeout' substring from the command line
+    timeout=`echo ${args} | ${SED} ${SEDOPT} 's/(.+)( -t [a-zA-Z0-9]+ )(.*)/\2/'`
+    # if the '-t timeout' is specified, use the timeout provided by the user
+    if [ "${timeout}" != "${args}" ] ; then    # match
+       # remove the '-t ' option
+       timeout=`echo ${timeout} | ${SED} ${SEDOPT} 's/-t //'`
+       timeout=`check_timeout ${timeout}`
+       [ $timeout = 0 ] && abort "Date format $1 not valid"
+       # clean the arguments
+       args=`echo ${args} | ${SED} ${SEDOPT} 's/(.+)( -t [a-zA-Z0-9]+ )(.*)/\1 \3/'`
+    else
+       # use the default value, no need to check for correctness, no need to clean arguments
+       timeout=`date --date="1day" +%s`                # default to 1 day
+    fi
+
+    # if the table rule is not present, add it
+    local table_rule=`${IPFW} show $S | grep "skipto tablearg" | grep "lookup jail $SLICE_TABLE"`
+    [ -z "$table_rule" ] && ipfw_init
+
+    debug "Timeout $timeout"
+    # Handle special requests: show and delete
+    case x"$cmd" in 
+    x"config") 
+       case x"$type" in 
+               xserver|xSERVER|xclient|xCLIENT|xservice|xSERVICE)
+                       do_config $SLICE_ID $timeout $type $args && return 0
+               ;;
+       esac
+       abort "'config' should be followed by {CLIENT|SERVER|SERVICE}"
+       ;;
+    x"delete") 
+       do_delete 1 $SLICE_ID $type $args
+       ;;
+    x"refresh") 
+       do_refresh $SLICE_ID $type $args $timeout && return 0
+       ;;
+    x"show")
+       # XXX filter out sliver rules
+       [ "$type" = "rules" ] && ${IPFW} show && return 0
+       [ "$type" = "pipes" ] && ${IPFW} pipe show && return 0
+       abort "'show' should be followed by {rules|pipes}"
+       ;;
+    x"super")
+       [ $SLICE_ID = 0 ] && do_super $type $args && return 0
+       abort "no permission for ipfw-be super execution"
+       ;;
+    x"help")
+       do_help && return 0
+       ;;
+    *)
+       # help XXX to be done
+       abort "'command' should be one of {show|config|delete|refresh|release}"
+       ;;
+    esac
+}
+
+# validate the timeout
+check_timeout() { # timeout
+    local tt=`date --date="${1}" +%s`
+    [ "$?" != "0" ] && echo 0 && return
+    echo $tt
+}
+
+do_config() { # slice_id timeout type arg IN pipe_conf OUT pipe_conf
+    local slice_id=$1; shift
+    local timeout=$1; shift
+    local type=$1; shift
+    local arg=$1; shift        # XXX addr not yet implemented
+    local p h;                 # port and optional hostname
+
+    [ "$1" != "IN" ] && abort "Missing addr:port, or IN requested"
+    shift
+
+    # read pipe in configuration
+    i=""
+    while [ "$1" != "" -a "$1" != "OUT" ] ; do
+       i="$i $1"
+       shift
+    done
+    CONFIG_PIPE_IN="$i"                # XXX local ?
+    [ "$CONFIG_PIPE_IN" = "" ] && abort "Missing pipe in configuration"
+
+    [ "$1" != "OUT" ] && abort "Missing pipe in configuration, or missing OUT"
+    shift
+
+    # read pipe out configuration
+    i=""
+    while [ "$1" != "" ] ; do
+       i="$i $1"
+       shift
+    done
+    CONFIG_PIPE_OUT="$i"       # XXX local ?
+    [ "$CONFIG_PIPE_OUT" = "" ] && abort "Missing pipe out configuration"
+
+
+    # process the argument (port and hostname are separated by a @)
+    # split the argument, and prepare the remote host configuration string
+    p=`echo $arg | cut -s -d "@" -f1-` # empty it there is no separator
+    if [ "$p" = "" ] ; then
+       p=$arg
+    else
+       p=`echo $arg | cut -d "@" -f1`
+       h=`echo $arg | cut -d "@" -f2`
+    fi
+
+    # A port value is mandatory
+    [ "$p" = "" ] && abort "A port value is mandatory."
+
+    # SERVICE do not support remote hostname filtering
+    [ $type = "service" ] && [ "$h" != "" ] && \
+       abort "The service configuration do not support filtering remote hostnames."
+
+    debug "Configuration Required:"
+    debug "slice_id: $SLICE_ID"
+    debug "type: $type"
+    debug "full arg: $arg"
+    debug "mandatory port(s): $p optional hostname(s): $h"
+    debug "timeout: $timeout"
+    debug "IN: $CONFIG_PIPE_IN"
+    debug "OUT: $CONFIG_PIPE_OUT"
+    debug "-----------------------"
+
+    # check if the link is already configured
+    debug "Search for slice_id: ${slice_id} type: ${type} port: ${arg}"
+
+    set `find_allocate ${slice_id} ${type} ${arg}`
+    local ipfw_rule=$1 pipe_index=$2 new_rule=$3
+
+    [ ${ipfw_rule} = 0 ] && abort "No resources available"
+    debug "Found or allocated resources ipfw_rule: ${ipfw_rule} and pipe_index: ${pipe_index}"
+
+    add_rule $slice_id $new_rule $type $arg $ipfw_rule $pipe_index $timeout
+    hook_call $type $port $rule_base $pipe_base $timeout
+    return 0; # link configured, exit
+}
+
+#
+# acquire the lock XXX check lockfile
+acquire_lock() {
+    [ "$TEST" = 1 ] && return
+    lockfile -s 0 -r 0 $lockfile 2> /dev/null
+    if [ $? -ne 0 ] ; then
+       echo "lock acquisition failed"
+       exit -1
+    fi
+}
+
+#
+# release the lock
+release_lock() {
+    rm -f $lockfile
+}
+
+#
+# initialize the firewall with PlanetLab default rules
+ipfw_init() {
+       ${IPFW} -q delete $S
+       ${IPFW} -q delete $D
+       ${IPFW} add $S skipto tablearg lookup jail $SLICE_TABLE
+       ${IPFW} add $D allow all from any to any
+}
+
+#
+# if present, call a hook function
+# Arguments are:
+# slice_id type port rule_base pipe_base timeout
+hook_call() {
+       if [ -n "${HOOK}" -a -x "${HOOK}" ]; then
+               debug "Calling the hook function."
+               ${HOOK} ${SLICE_ID} "$*" &
+       fi
+}
+
+do_help() {
+       cat << EOF
+Usage:
+        ./neconfig {CLIENT|SERVER|SERVICE} arg [-t timeout]    \
+                IN <pipe in configuration> OUT <pipe out configuration>
+        ./netconfig show {rules|pipes}
+        ./netconfig delete {CLIENT|SERVER|SERVICE} arg
+        ./netconfig refresh [-t timeout] {CLIENT|SERVER|SERVICE} arg
+
+We support three modes of operation:
+
+  CLIENT programs on the node connect to remote ports
+       and/or addresses. Emulation intercepts traffic
+       involving those ports/addresses
+
+  SERVER programs on the node listen on specific ports.
+       Emulation intercepts traffic on those ports,
+       optionally limited to specific client addresses.
+
+  SERVICE the node runs both clients and servers,
+       we can only specify the ports on which emulation
+       is configured.
+
+  'arg' has the form PORTLIST[@ADDRLIST], where ADDRLIST is
+  optional and only supported for CLIENT and SERVER modes.
+  PORTLIST and ADDRLIST can be specified as any valid port
+  or address specifier in ipfw, e.g.
+    - a single value           443 or 10.20.30.40/24
+    - a comma-separated list   1111,2222,3333 1.2.3.4,5.6.7.8
+    - a range                  1111-2222 (only for ports)
+  Addresses can also be specified as symbolic hostnames, and
+  they are resolved when the rule is installed.
+  Note that they always indicate the remote endpoint.
+
+  On a given port a user can have one CLIENT and/or one SERVER
+  configuration or one SERVICE configuration.
+  When a SERVICE configuration is installed any existing CLIENT
+  and SERVER configuration on the same port are removed.
+  When a CLIENT or SERVER configuration is installed any existing
+  SERVICE configuration on the same port is removed.
+
+The pipe's configuration, both for the upstream and downstream link,
+follows the dummynet syntax. A quick and not exaustive example
+of the parameters that can be used to configure the delay,
+the bandwidth and the packet loss rate for a link follow:
+
+        IN|OUT delay 100ms bw 1Mbit/s plr 0.1
+
+The profile file, if present, should be located into the sliver's
+root directory.
+The full documentation is on the manpage[1].
+
+The timeout value follow the linux 'date' command format[2]
+and can be specified as follow:
+        1week
+        2hours
+        3days
+
+--- References:
+[1] http://www.freebsd.org/cgi/man.cgi?query=ipfw
+[2] http://linuxmanpages.com/man1/date.1.php
+EOF
+}
+
+#--- DOCUMENTATION AND INTERNAL ARCHITECTURE ---
+#
+# When a user configures an emulated link, we need to allocate
+# two pipes and one ipfw rule number to store the parameters.
+# Reconfigurations of existing links reuse the previous resources.
+# We keep track of all resources (pipes, rules and blocks of rules)
+# in a database stored in a text file, see DATABASE FORMAT below.
+#
+# Pipes are allocated in pairs. In the database each pair is numbered
+# from PIPE_MIN to PIPE_MAX. The actual pipe numbers for each pair are
+#
+#      ipfw_pipein = IPFW_PIPE_MIN + 2*(pipe_index-1)
+#      ipfw_pipeout = ipfw_pipein + 1
+#
+# The rules number is allocated within a block of M consecutive rules
+# for each slice. The block is allocated at the first configuration
+# of an emulated link, and deallocated when the last link is removed.
+# In the database, blocks are numbered from BLOCK_MIN to BLOCK_MAX,
+# and the range of rules for a given block_index is
+#
+#      ipfw_min_rule = RULE_BASE
+#      ipfw_max_rule = RULE_BASE + ((M-1)*block_index) -1
+#
+# All lookups, and the block allocation, are done in find_allocate().
+# The rule_number and pipe_index are written in the database
+# by add_rule() after checking the correctness of the request.
+#
+#
+#--- RULESET STRUCTURE ---
+# The ruleset is made of different sections, as follows:
+# - an initial block of rules, reserved and configurable by
+#   the root context only;
+# - a skipto rule (S), used to jump directly to the block
+#   associated with a given slice;
+# - a second block of reserved rules, to catch remaining traffic.
+#   This ends with rule number D which is an 'accept all';
+# - after D, we have a block of M rule numbers for each slice.
+#   Each of these blocks ends with an 'accept all' rule;
+# - finally, rule 65535 is the firewall's default rule.
+#
+# To summarize:
+#      1...S-1 first block of reserved rules
+#      S       skipto tablearg lookup jail 1
+#      S+1..D-1 ... second block of reserved rules
+#      D       allow ip from any to any
+#
+#      RULE_BASE <block of M entries for first user>
+#      RULE_BASE+M <block of M entry for second user ...>
+#      ...
+#
+#--- DATABASE FORMAT ---
+# The database is stored in a text file, and contains one record per
+# line with the following structure
+#
+#      XID     TYPE    arg1    arg2    ...
+#
+# Whitespace separates the fields. arg1, arg2, ... have different
+# meaning depending on the TYPE. XID is the slice ID.
+#
+# In the database we have the following records:
+# - one entry of type BLOCK for each slice with configured links.
+#   This entry represents the block_index of the block of M ipfw
+#   rules allocated to the slice, as follows:
+#
+#      XID     BLOCK   block_index
+#   (BLOCK_MIN <= block_index <= BLOCK_MAX)
+#
+# - one entry for each link (CLIENT, SERVER, SERVICE).
+#   The database entry for this info has the form
+#
+#      XID {CLIENT|SERVER|SERVICE} arg ipfw_rule pipe_index timeout
+# 
+#   'TYPE' reflects the configuration mode;
+#   'arg' is PORTLIST@ADDRLIST and is used as a search key together
+#      with the XID and TYPE;
+#   'ipfw_rule' is the unique ipfw rule number used for this
+#      emulated link. It must be within the block of M rule numbers
+#      allocated to the slice;
+#   'pipe_index' is the index of the pair of pipes used for the
+#      configuration;
+
+#-- main starts here
+debug "--- $0 START for $SLICENAME ---"
+
+# If the db does not exist, create it and clean rules and pipes
+[ ! -e ${DBFILE} ] && clean_db
+
+# A request to the vsys backend is composed by a single line of input
+read REQ                       # read one line, ignore the rest
+set_verbose ${REQ}             # use inital -v if present
+set_test ${REQ}                # use inital -t if present
+REQ="`filter ${REQ}`"  # remove -v and -q and invalid chars
+debug "--- processing <${REQ}>"
+acquire_lock                   # critical section
+process ${REQ}
+release_lock
+debug "--- $0 END ---"
+exit 0
diff --git a/exec/mknod b/exec/mknod
new file mode 100755 (executable)
index 0000000..2dc11b4
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+
+use strict;
+
+my $slicename=$ARGV[0];
+my $slice_dev="/vservers/$slicename/dev";
+
+my $name = <STDIN>;
+my $major = <STDIN>;
+my $minor = <STDIN>;
+chomp($name);
+chomp($major);
+chomp($minor);
+
+$name=~s/\.\.//g;
+system("mknod $slice_dev".$name."c $major $minor");
diff --git a/exec/reserve_tcp_port b/exec/reserve_tcp_port
new file mode 100755 (executable)
index 0000000..a9043ea
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+
+use strict;
+
+$|=1;
+
+my $slicename;
+my $xid;
+my $portnumber;
+my $fuser_cmd;
+my $pid;
+my @vinfo;
+my $foo;
+my $real_xid;
+
+$slicename = $ARGV[0];
+$xid = int(`id -u $slicename`) || die("Could not determine xid of $slicename\n");
+$portnumber = <STDIN>;
+chop($portnumber);
+
+if ($portnumber!~/^\d+$/) {
+        die("$portnumber is not a port number");
+}
+
+if ($portnumber<61001 || $portnumber>65535) {
+       die("$portnumber lies in the local port-rover range\n");
+}
+
+$fuser_cmd = "ncontext --nid $xid --migrate -- vcontext --xid $xid --migrate fuser -n tcp $portnumber 2>/dev/null";
+$pid = `$fuser_cmd` || die("Please bind to port $portnumber, e.g. run nc -l $portnumber."); 
+$pid=~s/\s+//g;
+
+my $cat_cmd;
+
+$cat_cmd = "chcontext --ctx 1 cat /proc/$pid/vinfo";
+$_ = `$cat_cmd`;
+@vinfo = split /\n/;
+($#vinfo>0) || die("Port reservation failed. Please try again.\n");
+
+$_=@vinfo[0];
+
+($foo,$real_xid) = split;
+
+if (int($real_xid)!=$xid) {
+    die("Port $portnumber belongs to user $real_xid, not to you.\n"); 
+}
+
+# OK. We're good
+# Only, slices are allowed only 1 port reservation/session
+
+if ( -f "/dev/shm/$slicename-port" ) {
+       print "You have already reserved the following port:\n";
+       system("cat /dev/shm/$slicename-port");
+       exit(1);
+}
+
+open FIL,">/dev/shm/$slicename-port";
+print FIL "$portnumber";
+close FIL;
+
+system("iptables -t mangle -A INPUT -m tcp -p tcp --dport $portnumber -j MARK --set-mark $xid");
diff --git a/exec/reserve_udp_port b/exec/reserve_udp_port
new file mode 100755 (executable)
index 0000000..909f3bc
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+
+use strict;
+
+$|=1;
+
+my $slicename;
+my $xid;
+my $portnumber;
+my $fuser_cmd;
+my $pid;
+my @vinfo;
+my $foo;
+my $real_xid;
+
+$slicename = $ARGV[0];
+$xid = int(`id -u $slicename`) || die("Could not determine xid of $slicename\n");
+$portnumber = <STDIN>;
+chop($portnumber);
+
+if ($portnumber!~/^\d+$/) {
+        die("$portnumber is not a port number");
+}
+
+if ($portnumber<61001 || $portnumber>65535) {
+       die("$portnumber lies in the local port-rover range\n");
+}
+
+$fuser_cmd = "ncontext --nid $xid --migrate -- vcontext --xid $xid --migrate fuser -n udp $portnumber 2>/dev/null";
+$pid = `$fuser_cmd` || die("Please bind to port $portnumber, e.g. run nc -ul $portnumber."); 
+$pid=~s/\s+//g;
+
+my $cat_cmd;
+
+$cat_cmd = "chcontext --ctx 1 cat /proc/$pid/vinfo";
+$_ = `$cat_cmd`;
+@vinfo = split /\n/;
+($#vinfo>0) || die("Port reservation failed. Please try again.\n");
+
+$_=@vinfo[0];
+
+($foo,$real_xid) = split;
+
+if (int($real_xid)!=$xid) {
+    die("Port $portnumber belongs to user $real_xid, not to you.\n"); 
+}
+
+# OK. We're good
+# Only, slices are allowed only 1 port reservation/session
+
+if ( -f "/dev/shm/$slicename-port" ) {
+       print "You have already reserved the following port:\n";
+       system("cat /dev/shm/$slicename-port");
+       exit(1);
+}
+
+open FIL,">/dev/shm/$slicename-port";
+print FIL "$portnumber";
+close FIL;
+
+system("iptables -t mangle -A INPUT -m udp -p udp --dport $portnumber -j MARK --set-mark $xid");
diff --git a/exec/rsyncauthlogs b/exec/rsyncauthlogs
new file mode 100755 (executable)
index 0000000..4914501
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+DEST="/vservers/$1/home/$1/"
+
+/usr/bin/rsync -a /var/log/secure* $DEST
diff --git a/exec/run_with_devices b/exec/run_with_devices
new file mode 100644 (file)
index 0000000..c0b2312
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/python -u
+# All vsys scripts should use STDOUT in unbuferred mode, or else sometimes your output will get bufferred and you will not see it till the buffer gets flushed.  
+
+import sys
+import os
+
+vsys_config_dir = "/etc/planetlab/vsys-attributes"
+
+slicename=sys.argv[1]
+sliceid = pwd.getpwnam(slicename).pw_uid
+
+arglines = map(string.strip, sys.stdin.readlines())
+command_name = arglines[0]
+device_names = arglines[1:]
+
+print "Validating interface names... ",
+# Validate interface names
+
+for vif in device_names:
+    if len(vif)>16:
+        print "Interface name %s invalid"%(vif)
+        sys.exit(1)
+    if re.match(r'(tun|tap)%d-\d+' % sliceid, vif ) is None:
+        print "Interface name %s does not match slice id %d."%(vif, sliceid)
+        sys.exit(1)
+    print "[OK]"
+
+# The interfaces have been validated. We don't need to validate the executable
+# path for escape hatches because we are going to use execve.
+
+pid = os.fork()
+if (pid):
+    # Close open fds before execve
+    print "Closing file descriptors."
+    for fd in xrange(3, 1023):
+        try:
+            os.close(fd)
+        except OSError:
+            pass
+    # Execute command
+    vserver_command = "/usr/sbin/vserver"
+    args = [slicename]
+    args += ['exec']
+    args += [command_name]
+
+    os.system('touch /etc/vservers/%s/spaces/net'%slicename)
+
+    try:    
+        os.execve(vserver_command, args)
+    except:
+        pass
+
+    os.system('rm /etc/vservers/%s/spaces/net'%slicename)
+else:
+    for vif in device_names:
+        os.system('/sbin/ip link set %s netns %d'%(vif, pid))
+
index e5cbd2f..cc800ce 100755 (executable)
@@ -1,7 +1,5 @@
 #!/bin/sh +x
 
-IP=/sbin/ip
-
 SLICE=$1
 SLICEID=`id -u $SLICE`
 read INDEX
@@ -11,17 +9,16 @@ read KEY
 LINK=${KEY}if${INDEX}
 
 modprobe ip_gre
-modprobe etun
 
 ### Setup EGRE tunnel
 EGRE=d$LINK
-$IP tunnel add $EGRE  mode gre/eth remote $REMOTE key $KEY
-$IP link set $EGRE up
+ip tunnel add $EGRE  mode gre type eth remote $REMOTE key $KEY ttl 64
+ip link set $EGRE up
 
 ### Setup etun
 ETUN0=a$LINK
 ETUN1=b$LINK
-echo $ETUN0,$ETUN1 > /sys/module/etun/parameters/newif
+ip link add name $ETUN0 type veth peer name $ETUN1
 ifconfig $ETUN0 mtu 1458 up
 ifconfig $ETUN1 up
 
@@ -44,7 +41,7 @@ cat > $GRAB <<EOF
 
 read PID
 
-chcontext --ctx 1 -- echo \$PID > /sys/class/net/$ETUN0/new_ns_pid 
+ip link set $ETUN0 netns \$PID
 EOF
 chmod +x $GRAB
 
@@ -79,7 +76,7 @@ read NULL
 iptables -t mangle -D FORWARD -o $BRIDGE -j MARK --set-mark $SLICEID
 
 # Get rid of etun devices, only need name of one of them
-echo $ETUN1 > /sys/module/etun/parameters/delif
+ip link delete dev $ETUN1 
 
 # Get rid of bridge
 ifconfig $BRIDGE down
index 64be40b..9a0c4f5 100755 (executable)
@@ -1,22 +1,18 @@
 #!/bin/sh +x
 
-IP=/sbin/ip
-
 SLICE=$1
 SLICEID=`id -u $SLICE`
 read KEY
 
-modprobe etun
-
 ### Setup etun
 ETUN0=nat$KEY
 ETUN1=natx$KEY
-echo $ETUN0,$ETUN1 > /sys/module/etun/parameters/newif
-ifconfig $ETUN1 10.0.$KEY.1 up
+ip link add name $ETUN0 type veth peer name $ETUN1
+ifconfig $ETUN1 10.0.$KEY.1/24 up
 
-/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-/sbin/iptables -A FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-/sbin/iptables -A FORWARD -i $ETUN1 -o eth0 -j ACCEPT
+iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+iptables -A FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
+iptables -A FORWARD -i $ETUN1 -o eth0 -j ACCEPT
 
 ### Create "grab link" script
 GRAB=/vsys/local_grab-$ETUN0
@@ -27,7 +23,7 @@ cat > $GRAB <<EOF
 
 read PID
 
-chcontext --ctx 1 -- echo \$PID > /sys/class/net/$ETUN0/new_ns_pid 
+ip link set $ETUN0 netns \$PID 
 EOF
 chmod +x $GRAB
 
@@ -41,12 +37,12 @@ cat > $DELETE <<EOF
 read NULL
 
 # Remove iptables rules
-/sbin/iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
-/sbin/iptables -D FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-/sbin/iptables -D FORWARD -i $ETUN1 -o eth0 -j ACCEPT
+iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
+iptables -D FORWARD -i eth0 -o $ETUN1 -m state --state RELATED,ESTABLISHED -j ACCEPT
+iptables -D FORWARD -i $ETUN1 -o eth0 -j ACCEPT
 
 # Get rid of etun devices, only need name of one of them
-echo $ETUN1 > /sys/module/etun/parameters/delif
+ip link delete dev $ETUN1 
 
 # Clean up files
 rm -f $GRAB $GRAB.acl
diff --git a/exec/sliceip b/exec/sliceip
new file mode 100755 (executable)
index 0000000..8316856
--- /dev/null
@@ -0,0 +1,498 @@
+#!/bin/bash
+#
+# Giovanni Di Stasi
+# Copyright (C) 2009 UniNa
+# $Id$
+#
+# This is a backend script to be used with
+# the vsys system. It allows to define and 
+# manage slice-specific routing tables. 
+# The routing rules added to these routing 
+# tables affect only the respective slices.  
+#
+# This script is meant to be called from a 
+# frontend script in the slice environment. 
+#
+# Fronted usage:
+# sliceip enable <interface> 
+#   This is the first command to issue; it enables the use
+#   of the interface for the slice. This command has to be issued 
+#   for each interface involved in the slice-specific routing rules.
+#
+# sliceip disable <interface> 
+#   This is to disable the use of the interface for the slice.
+#
+# sliceip route show 
+#   This command shows the current routing rules of the
+#   slice-specific routing table
+#
+# sliceip route add to <destination> via <gateway> dev <interface>
+#   This command adds a rule to reach <destination> through the host
+#   <gateway> that can be reached on the interface <interface>
+# ...
+# 
+# sliceip in general supports all the commands of the "ip" command of
+# the "iproute2" suite. Refer to ip manpage for further information.
+# 
+# Some examples:
+#      sliceip route add to 143.225.229.142 via 192.168.8.2 dev ath0
+#      sliceip route add default via 10.1.1.1 dev ath0
+#
+# If you want to test the script from the root context you need 
+# to call it as vsys would do:
+# sliceip <slice_name>
+# Then you can issue to its standard input the commands previously explained
+# (but you have to remove the initial "sliceip"). Ex.:
+#       route add to 143.225.229.142 via 192.168.8.2 dev ath0
+
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin 
+
+# sliver wich called the script
+sliver=$1
+
+#files used
+RT_TABLES="/etc/iproute2/rt_tables"
+INT_FILE="/tmp/slcroute_ifns"
+
+# routing tables from 100 to 255 are used
+FIRST_TABLE=100
+
+DEBUG=0
+
+#this script can also work on a Linux machine, in wich case
+#it enables user-specific routing tables
+LINUX_ENV=0 # 0 - Linux host;
+           # does not work for the icmp protocol
+
+PLANET_ENV=1 # 1 - PlanetLab context (slice-specific routing) 
+
+#select the PlanetLab environment
+ENVIRONMENT=$PLANET_ENV
+
+
+# enable an interface for the slice specific routing rules
+# and initialise the slice routing table
+function enable_interface(){ # $1 calling sliver; $2 interface to enable
+       local sliver=$1
+       local interface="$2"
+       local ip=`get_address $interface`
+
+       if [[ "" == $ip ]]; then
+               echo "Failed in getting address of $interface"
+               return 1
+       fi
+
+       #create the sliceip netfilter chains
+       check_chains
+
+       local nid=`get_nid $sliver`
+       local num_active=`get_num_activated $sliver`
+
+       if ! is_active $sliver $interface; then
+               if [[ $num_active == 0 ]]; then
+                               #define the routing table for the slice and set some iptables rules in order to mark user's packets;                    
+                               create_table $sliver
+               fi
+
+               #Adds an SNAT rule to set the source IP address of packets that are about to go out through $interface.
+               #The kernel sets the source address of packets when the first routing process happens (following the rules 
+               #of the main routing table); when the rerouting process happens (following the user/slice specific rules) 
+               #the source address is not modified. Consequently, we need to add this rule to change the source ip address 
+               #to the $interface source address.
+               exec "iptables -t nat -A $NAT_POSTROUTING -o $interface -j SNAT --to-source $ip -m mark --mark $nid"
+
+               set_active $sliver $interface $ip               
+       else
+               local old_ip=`get_ip_from_file $sliver $interface`
+       
+               #if the ip of the interface has changed, set the new SNAT rule
+               if [[ $old_ip != $ip ]]; then
+                       #remove the rule for the old ip
+                       exec "iptables -t nat -D $NAT_POSTROUTING -o $interface -j SNAT --to-source $old_ip -m mark --mark $nid"
+                       #insert the new rule                    
+                       exec "iptables -t nat -A $NAT_POSTROUTING -o $interface -j SNAT --to-source $ip -m mark --mark $nid"    
+                       set_deactivated $sliver $interface $old_ip
+                       set_active $sliver $interface $ip
+               fi
+
+
+       fi
+
+}
+
+# disable the interface for the slice-specific routing rules
+function disable_interface(){
+       local sliver=$1
+       local interface=$2
+       local ip=`get_ip_from_file $sliver $interface`  
+       local nid=`get_nid $sliver`
+
+       if is_active $sliver $interface >/dev/null 2>&1; then
+               exec "iptables -t nat -D $NAT_POSTROUTING -o $interface -j SNAT --to-source $ip -m mark --mark $nid"
+               
+               local num_ifn_on=`get_num_activated $sliver`
+               
+               if [[ $num_ifn_on == 1 ]]; then
+                       delete_table $sliver
+               fi
+               set_deactivated $sliver $interface
+       fi
+
+}
+
+# wrapper function used to execute system commands
+function exec(){
+       local command=$1        
+
+       if ! [[ $command ]]; then
+               echo "Error in exec. No argument."
+               exit 1  
+       else
+               if ! $command; then
+                       if [[ $DEBUG == 1 ]]; then echo "Error executing \"$1\""; fi
+                       exit 1
+               fi
+       fi
+
+}
+
+# decides wich id to use for the slice-specific routing table
+function get_table_id(){
+       local sliver=$1
+       k=$FIRST_TABLE
+
+       while [[ $k < 255 ]] && grep $k $RT_TABLES >/dev/null 2>&1 ; do
+               k=$((k+1))
+       done
+
+       if [[ $k == 255 ]]; then
+               logm "No routing tables available. Exiting."
+               return 1
+       fi
+       
+       echo $k
+}
+
+
+# create the slice-specifig routing table
+function create_table(){
+       local sliver=$1
+       local table_name=`get_table_name $sliver`
+       local table_id=`get_table_id $sliver`   
+       local temp_nid=`get_temp_nid $sliver`
+
+       if ! grep $table_name $RT_TABLES > /dev/null 2>&1; then
+               echo "$table_id $table_name" >> $RT_TABLES
+       else
+               echo "WARNING: $table_name routing table already defined."
+       fi
+
+       set_routes $sliver $table_name
+
+       return 0
+}
+
+# delete the slice-specific routing table
+function delete_table(){
+       local sliver=$1
+       local table_name=`get_table_name $sliver`
+       local table_id=`get_nid $sliver`        
+       local temp_nid=`get_temp_nid $sliver`
+
+       if ! grep $table_name $RT_TABLES > /dev/null 2>&1; then
+               return 1                        
+       else
+               exec "ip route flush table $table_name" >/dev/null 2>&1
+               unset_routes $sliver $table_name
+               remove_line "$RT_TABLES" "$table_name"          
+       fi
+
+       return 0
+}
+
+# remove a line from a file
+function remove_line(){
+       local filename=$1
+       local regex=$2
+
+       #remove interface line from the file
+       exec "sed -i /${regex}/d $filename"
+}
+
+# get the slice-specific routing table name
+function get_table_name(){
+       local sliver=$1;
+       echo "${sliver}_slcip"
+}
+
+#remove files used by sliceip and the added routing tables 
+function clean_iproute_conf(){
+       while grep "slcip" $RT_TABLES >/dev/null 2>&1; do
+               remove_line $RT_TABLES "slcip"
+       done
+
+       rm -f ${INT_FILE}-*
+
+}
+
+#get slice network id
+function get_nid(){
+    id -u ${1}
+}
+
+# set the firewall rules. Mainly, it asks VNET+ to set the netfilter mark of packets belonging to the slice to the slice-id
+# and then associates those packets with the routing table allocated for that slice.
+function set_routes(){
+       local sliver=$1
+       local table_name=$2
+       local sliver_nid=`get_nid $sliver`
+       local temp_nid=`get_temp_nid $sliver`
+
+       if [ $ENVIRONMENT == $PLANET_ENV ]; then        
+               #Linux kernel triggers a rerouting process, wich is needed to perfom slice-specific routing,  
+               #if it sees that the netfilter mark has been altered in the iptables mangle chain.
+               #As VNET+ sets the netfilter mark of some packets in advance (to the slice-id value) before they enter the iptables mangle chain, 
+               #we need to change it here (otherwise the rerouting process is not triggered for them).
+               exec "iptables -t mangle -I $MANGLE_OUTPUT 1 -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid"
+
+               #make sure the netfilter mark of those "strange packets" won't be changed by the following rule
+               exec "iptables -t mangle -I $MANGLE_OUTPUT 2 -m mark --mark $temp_nid -j RETURN"
+
+               #Here we ask VNET+ to set the netfilter mark for the remaining packets (to the slice-id) 
+               #we need to call this only once
+               if [[ $first_time == 1 ]]; then
+                       exec "iptables -t mangle -A $MANGLE_OUTPUT -j MARK --copy-xid 0x00"
+               fi              
+
+       elif [ $ENVIRONMENT == $LINUX_ENV ]; then
+               #the same in the case of a "plain" Linux box. In this case we do not use VNET+ but
+               #the owner module of iptables.
+               exec "iptables -t mangle -A $MANGLE_OUTPUT -m owner --uid-owner $sliver_nid -j MARK --set-mark $sliver_nid"
+       fi
+
+       if [ $ENVIRONMENT == $PLANET_ENV ]; then        
+               #Here the netfilter mark is restored to the slice-id value for the "strange packets"
+               exec "iptables -t mangle -A $MANGLE_POSTROUTING -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid"
+       fi
+
+       #Set the routing for the slice to be applied following the rules in $table_name"
+       #for the slice packets...
+       exec "ip rule add fwmark $sliver_nid table $table_name" 
+       #...and for the "strange packets"       
+       exec "ip rule add fwmark $temp_nid table $table_name"   
+
+       exec "ip route flush cache"  >/dev/null 2>&1
+}
+
+
+# remove the firewall rules. 
+function unset_routes(){
+       local sliver=$1
+       local table_name=$2
+       local sliver_nid=`get_nid $sliver`
+       local temp_nid=`get_temp_nid $sliver`
+       
+       if [ $ENVIRONMENT == $PLANET_ENV ]; then         
+               #removes the rules for the netfilter marks (for the "strange packets")
+               exec "iptables -t mangle -D $MANGLE_OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid"
+               exec "iptables -t mangle -D $MANGLE_OUTPUT -m mark --mark $temp_nid -j RETURN"
+               
+               #removes the rule for restoring the original mark
+               exec "iptables -t mangle -D $MANGLE_POSTROUTING -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid"
+
+       elif [ $ENVIRONMENT == $LINUX_ENV ]; then
+               #removes the rules that asks the owner module of iptables to set the netfilter mark to the user-id
+               exec "iptables -t mangle -D $MANGLE_OUTPUT -m owner --uid-owner $sliver_nid -j MARK --set-mark $sliver_nid"
+       fi
+
+       exec "ip rule del fwmark $temp_nid table $table_name"
+       exec "ip rule del fwmark $sliver_nid table $table_name" 
+
+       exec "ip route flush cache"
+
+}
+
+# additional iptables chains where sliceip inserts its rules
+NAT_POSTROUTING="sliceip"
+MANGLE_OUTPUT="sliceip_output"
+MANGLE_POSTROUTING="sliceip_postrouting"
+
+# create the chains
+check_chains(){
+       first_time=0
+
+       #create the chain where SNAT is performed
+       if iptables -t nat -N $NAT_POSTROUTING >/dev/null 2>&1; then
+               #it's the first time sliceip is called, the chain was not defined               
+               first_time=1            
+               
+               #create a chain where the netfilter mark is set
+               exec "iptables -t mangle -N $MANGLE_OUTPUT"
+
+               #create a chain where the netfilter mark for some packets is restored (see set_routes)
+               exec "iptables -t mangle -N $MANGLE_POSTROUTING"
+
+               #add the rules to take packets to the previously defined chains
+               exec "iptables -t nat -A POSTROUTING -j $NAT_POSTROUTING"               
+               exec "iptables -t mangle -A OUTPUT -j $MANGLE_OUTPUT"
+               exec "iptables -t mangle -I POSTROUTING 1 -j $MANGLE_POSTROUTING"
+
+               #cleaning up
+               clean_iproute_conf
+       fi
+}
+
+# get the ip address of an interface
+function get_address(){
+       local interface=$1      
+       local ip=""
+       
+       ip=`ifconfig $interface | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1`;
+
+       if valid_dotted_quad $ip; then 
+               echo $ip;
+       else 
+               echo "";
+       fi      
+                       
+}
+
+# get the temporary mark to be applied to the packets of the slice
+function get_temp_nid(){
+       local sliver_nid=`get_nid $1`
+       local temp_nid=$((0x20000+$sliver_nid))
+       echo $temp_nid
+}
+
+# log function
+function logm(){
+       logger $1
+}
+
+# get the name of the filename in wich we store information about
+# the interfaces in use by the user
+function get_filename_sliver(){
+       local sliver=$1
+       echo "${INT_FILE}-$sliver"
+}
+
+function set_active(){
+       local sliver=$1
+       local interface=$2
+       local ip=$3
+       local filename="${INT_FILE}-$sliver"
+       echo "$interface $ip" >> $filename
+}
+
+function set_deactivated(){
+       local sliver=$1
+       local interface=$2
+       local filename=`get_filename_sliver $sliver`
+       remove_line $filename $interface
+}
+
+function is_active(){
+       local sliver=$1
+       local interface=$2
+       local filename=`get_filename_sliver $sliver`
+
+       if grep $interface $filename >/dev/null 2>&1; then
+               return 0
+       else
+               return 1
+       fi
+}
+
+function get_num_activated(){
+       local sliver=$1
+       local filename=`get_filename_sliver $sliver`
+
+       if ! [ -e $filename ]; then
+               echo 0;
+       else
+               wc -l $filename | cut -f 1 -d " ";
+       fi
+}
+
+
+function get_ip_from_file(){
+       local sliver=$1
+       local interface=$2
+
+       local filename=`get_filename_sliver $sliver`
+
+       cat $filename | grep $interface | cut -d " " -f 2
+}
+
+
+# check ip addresses  
+function valid_dotted_quad(){
+    oldIFS=$IFS
+    IFS=.
+    set -f
+    set -- $1
+    if [ $# -eq 4 ]
+    then
+      for seg
+      do
+        case $seg in
+            ""|*[!0-9]*) return 1; break ;; ## Segment empty or non-numeric char
+            *) [ $seg -gt 255 ] && return 2 ;;
+        esac
+      done
+    else
+      return 3 ## Not 4 segments
+    fi
+    IFS=$oldIFS
+    set +f
+    return 0;
+}
+
+
+# BEGIN
+# the script starts here
+
+if [[ $sliver == "" ]]; then
+       echo "I need the first argument (the sliver name)";
+       exit 1
+fi
+
+# read a line from the vsys pipe
+read line
+
+# separate the first word of the line from the others
+command=`echo ${line%% *}`
+rest=`echo ${line#* }`
+
+case "$command" in
+  enable)
+       logger "sliceip command received from $sliver: $line"   
+       enable_interface $sliver "$rest"
+       ;;
+
+  disable)
+       logger "sliceip command received from $sliver: $line"   
+       disable_interface $sliver "$rest"
+       ;;
+
+  *)
+       logger "sliceip command received from $sliver: $line"
+       table_sliver=`get_table_name $sliver`
+
+       if ! grep "$table_sliver" $RT_TABLES >/dev/null 2>&1; then
+               echo "Error. The slice routing table is not defined. Execute sliceip enable <interface>."
+               exit 1
+       else 
+               #add the routing rule - ip is called with the same parameters of sliceip but the indication of 
+               #the table in wich the rule is to be inserted is appended               
+               exec "ip $line table $table_sliver"
+       fi  
+       ;;
+
+esac
+
+exit 0
+
+
+
diff --git a/exec/umount b/exec/umount
new file mode 100755 (executable)
index 0000000..7bde900
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+
+my $slicename=$ARGV[0];
+my $slice_dir="/vservers/$slicename/";
+my $localpath = <STDIN>;
+
+chomp($localpath);
+
+$localpath=$slice_dir.$localpath;
+
+my $pathtest;
+
+$pathtest='';
+while ($localpath=~/(\/?[\w\d\-_]+\/?)/g) {
+    $pathtest=$pathtest.$1;
+}
+
+if ($pathtest ne $localpath) {
+    die "$localpath is not a safe path";
+}
+
+my $mntcmd="/bin/umount $localpath";
+system($mntcmd);
+
+if ($?) {
+    print "Mount failed: $?";
+}
diff --git a/exec/vif_down b/exec/vif_down
new file mode 100755 (executable)
index 0000000..8f87a89
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+# VSYS script to ifdown per-slice virtual network interfaces from the root slice
+#   Thom Haddow - 06/10/09
+#
+# Gets slice name as argv[1]
+# Takes remaining args on stdin:
+#   - Interface name (eg [tun|tap]<sliceid>-<n>)
+
+import sys
+import pwd
+import os
+import re
+
+
+if len(sys.argv) != 2: sys.exit(1)
+
+# VSYS scripts get slicename as $1
+slicename=sys.argv[1]
+sliceid = pwd.getpwnam(slicename).pw_uid
+
+
+# Read interface name
+vif = sys.stdin.readline().strip() # interface name
+
+
+# Validate interface name
+if len(vif)>16:
+    print >>sys.stderr, "Interface name %s invalid"%(vif)
+    sys.exit(1)
+
+if re.match(r'(tun|tap)%d-\d+' % sliceid, vif ) is None:
+    print >>sys.stderr, "Interface name %s does not match slice id %d."%(vif, sliceid)
+    sys.exit(1)
+
+
+
+# Bring interface down
+
+cmd_ifconfig = "/sbin/ifconfig %s down" % (vif)
+os.system(cmd_ifconfig)
+
+# Remove iptables rules
+cmd_iptables_del_in = "/sbin/iptables -D INPUT -i %s -m mark ! --mark %d -j DROP 2>/dev/null" % (vif, sliceid)
+cmd_iptables_del_out = "/sbin/iptables -D OUTPUT -o %s -m mark ! --mark %d -j DROP 2>/dev/null" % (vif, sliceid)
+
+os.system(cmd_iptables_del_in)
+os.system(cmd_iptables_del_out)
diff --git a/exec/vif_up b/exec/vif_up
new file mode 100755 (executable)
index 0000000..2829b58
--- /dev/null
@@ -0,0 +1,159 @@
+#!/usr/bin/python
+# VSYS script to configure per-slice virtual network interfaces from the root slice
+#   Thom Haddow - 06/10/09
+#
+# Gets slice name as argv[1]
+# Takes remaining args on stdin:
+#   - Interface name (eg [tun|tap]<sliceid>-<n>)
+#   - IP address (eg 1.2.3.4)
+#   - Netmask (as int, e.g. 24)
+#   - Followed by options as name=value pairs
+
+import sys
+import pwd
+import re
+import socket
+import struct
+import os
+import string
+
+vsys_config_dir = "/etc/planetlab/vsys-attributes"
+
+if len(sys.argv) != 2: sys.exit(1)
+
+# VSYS scripts get slicename as $1
+slicename=sys.argv[1]
+sliceid = pwd.getpwnam(slicename).pw_uid
+
+netblock_config=os.path.join(vsys_config_dir,slicename,"vsys_vnet")
+
+# Read netblock allocation file
+base = None
+
+for netblock in open(netblock_config,'r'):
+    base, mask = netblock.split('/')
+
+if base is None:
+    print >>sys.stderr, "Could not find entry for slice %s in netblock config file %s" % (slicename, netblock_config)
+    sys.exit(1)
+
+
+### Read args from stdin
+arglines = map(string.strip, sys.stdin.readlines())
+
+if len(arglines)<3:
+    print >>sys.stderr, "Insufficient argument lines."
+    sys.exit(1)
+
+vif = arglines[0] # interface name
+vip = arglines[1] # IP
+vmask = int(arglines[2]) # netmask as int
+
+# Create options list
+if len(arglines)>3:
+    options = arglines[3:]
+else:
+    options = []
+
+# Convert network base addr to int format by unpacking as 32bit net-ordered long (!L)
+base_int = struct.unpack('!L',socket.inet_aton(base))[0]
+mask = int(mask)
+
+
+### Validate args
+# Validate interface name
+if len(vif)>16:
+    print >>sys.stderr, "Interface name %s invalid"%(vif)
+    sys.exit(1)
+
+if re.match(r'(tun|tap)%d-\d+' % sliceid, vif ) is None:
+    print >>sys.stderr, "Interface name %s does not match slice id %d."%(vif, sliceid)
+    sys.exit(1)
+
+
+
+# Validate requested IP and convert to int format.
+try:
+    vip_int = struct.unpack('!L',socket.inet_aton(vip))[0]
+except socket.error:
+    print >>sys.stderr, "Invalid IP: %s" % vip
+    sys.exit(1)
+
+# Check IP is in netblock
+if (vip_int>>(32-mask)) != (base_int>>(32-mask)):
+    print >>sys.stderr, "Requested IP %s not in netblock %s/%d" % (vip,base,mask)
+    sys.exit(1)
+
+# TODO. Check IP is not in use?
+
+# Validate mask: Check requested mask is sane and within our netblock
+if vmask>32 or vmask <8:
+    print >>sys.stderr, "Requested netmask /%d is invalid" %(vmask)
+    sys.exit(1)
+    
+if vmask<mask:
+    print >>sys.stderr, "Requested netmask /%d larger than allocation /%d" %(vmask, mask)
+    sys.exit(1)
+
+
+
+### Process options
+
+opt_txqueuelen = None
+opt_rp_filter = None
+
+
+for optionline in options:
+    if len(optionline)==0: continue
+    try:
+        opt, val = optionline.split('=')
+    except:
+        print >>sys.stderr, "Bad option line: \"%s\"" % (optionline)
+        sys.exit(1)
+
+    if opt=="rp_filter":
+        if val=="0":
+            opt_rp_filter="0"
+        elif val=="1":
+            opt_rp_filter="1"
+        else:
+            print >>sys.stderr, "rp_filter value invalid: \"%s\"" % (val)
+            sys.exit(1)
+
+    elif opt=="txqueuelen":
+        intval = int(val)
+        if intval<1 or intval>10000:
+            print >>sys.stderr, "txqueuelen value %s out of range 1-10000" % (val)
+            sys.exit(1)
+        opt_txqueuelen = intval
+
+    else:
+        print >>sys.stderr, "Unknown option: \"%s\"" % (opt)
+        sys.exit(1)
+
+
+        
+### Configure interface
+
+if opt_txqueuelen is None:
+    cmd_ifconfig = "/sbin/ifconfig %s %s/%d" % (vif, vip, vmask)
+else:
+    cmd_ifconfig = "/sbin/ifconfig %s %s/%d txqueuelen %d" % (vif, vip, vmask, opt_txqueuelen)
+
+os.system(cmd_ifconfig)
+
+# Add iptables rules (Clearing old ones first, if they exist)
+cmd_iptables_in = "/sbin/iptables -A INPUT -i %s -m mark -m state --state NEW ! --mark %d -j DROP" % (vif, sliceid)
+cmd_iptables_del_in = "/sbin/iptables -D INPUT -i %s -m mark -m state --state NEW ! --mark %d -j DROP 2>/dev/null" % (vif, sliceid)
+cmd_iptables_out = "/sbin/iptables -A OUTPUT -o %s -m state --state NEW -m mark ! --mark %d -j DROP" % (vif, sliceid)
+cmd_iptables_del_out = "/sbin/iptables -D OUTPUT -o %s -m state --state NEW -m mark ! --mark %d -j DROP 2>/dev/null" % (vif, sliceid)
+
+os.system(cmd_iptables_del_in)
+os.system(cmd_iptables_in)
+os.system(cmd_iptables_del_out)
+os.system(cmd_iptables_out)
+
+# Process additional options
+if opt_rp_filter is not None:
+    rp_cmd = "/sbin/sysctl net.ipv4.conf.%s.rp_filter=%s" % (vif, opt_rp_filter)
+    os.system(rp_cmd)
diff --git a/fd_bmsocket.c b/fd_bmsocket.c
new file mode 100644 (file)
index 0000000..6a830ed
--- /dev/null
@@ -0,0 +1,73 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "fdpass.h"
+
+#define MAX_BUFSIZE (32*1024*1024)
+
+/*------------------------------------------------------------------*/
+void
+receive_argument(int control_fd, int *rcvbuf, int *sndbuf)
+{
+  if (recv(control_fd, rcvbuf, sizeof(int), 0) != sizeof(int)) {
+    fprintf(stderr, "receiving the first argument failed\n");
+    exit(-1);
+  }
+  if (recv(control_fd, sndbuf, sizeof(int), 0) != sizeof(int)) {
+    fprintf(stderr, "receiving the first argument failed\n");
+    exit(-1);
+  }
+}
+/*------------------------------------------------------------------*/
+int 
+main(int argc, char *argv[]) 
+{
+    int control_channel_fd, magic_socket;
+    int rcvbufsize = 0, sndbufsize = 0;
+    
+    if (argc < 3) {
+        printf("This script is called by vsys.\n");
+        exit(1);
+    }
+
+    sscanf(argv[2],"%d", &control_channel_fd);
+
+    /* receive paramaters: rcvbufsize and sndbufsize */
+    receive_argument(control_channel_fd, &rcvbufsize, &sndbufsize);
+    if (rcvbufsize > MAX_BUFSIZE)
+      rcvbufsize = MAX_BUFSIZE;
+    if (sndbufsize > MAX_BUFSIZE)
+      sndbufsize = MAX_BUFSIZE;
+
+    magic_socket = socket(AF_INET, SOCK_STREAM, 0);
+    if (magic_socket == -1) {
+      fprintf(stderr, "Error creating socket: %d\n", errno);
+      exit(1);
+    }
+
+    /* buffer size <= 0 means we should ignore the parameter */
+    if (rcvbufsize > 0) {
+      if (setsockopt(magic_socket, 
+                    SOL_SOCKET, 
+                    SO_RCVBUFFORCE, 
+                    &rcvbufsize, sizeof(unsigned int))) {
+        fprintf(stderr, "Error calling setsockopt for RCVBUFFORCE: %d\n", 
+               errno);
+        exit(1);
+      }
+    }
+    if (sndbufsize > 0) {
+      if (setsockopt(magic_socket, 
+                    SOL_SOCKET, 
+                    SO_SNDBUFFORCE, 
+                    &sndbufsize, sizeof(unsigned int))) {
+        fprintf(stderr, "Error calling setsockopt for SNDBUFFORCE: %d\n", 
+               errno);
+        exit(1);
+      }
+    }
+
+    send_fd(control_channel_fd, magic_socket);
+}
diff --git a/fd_fusemount.c b/fd_fusemount.c
new file mode 100644 (file)
index 0000000..5c29c98
--- /dev/null
@@ -0,0 +1,138 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "fdpass.h"
+
+unsigned int rcvbuf = 16*1024*1024;
+unsigned int arg_length = 128;
+unsigned int mountflags = MS_NODEV | MS_NOSUID;
+
+FILE *logfd;
+
+void receive_argument(int control_channel_fd, char *source) {
+    int received;
+    received=recv(control_channel_fd, source, arg_length, 0);
+    if (received<arg_length) {
+        fprintf(logfd,"Error receiving arguments over the control buffer\n");
+        close(logfd);
+        exit(1);
+    }
+}
+
+int set_magic_fd (char *data, int new_fd) {
+    char *ptr;
+    int fd;
+
+    data[arg_length-1]='\0';
+    ptr = strstr(data,"fd=");
+    if (!ptr)
+        return -1;
+
+    // Found two fd= expressions
+    if (strstr(ptr+3,"fd="))
+        return -1;
+
+    if (*(ptr+3)!='\0') {
+        char *new_data = (char *) malloc(arg_length);
+        char *head = (char *) malloc(arg_length);
+        char *tail;
+        sscanf(ptr+3,"%d",&fd);
+        strncpy(head, data, ptr - data);
+        tail = strchr(ptr+3,',');
+        sprintf(new_data,"%sfd=%d%s",head,new_fd,tail);
+        strcpy(data,new_data);
+        free(head);
+        free(new_data);
+        return fd;
+    }
+    else
+        return -1;
+}
+
+void check_source(char *source) {
+    source[arg_length-1]='\0';
+    if (strchr(source,'/') || strstr(source,"..")) {
+        fprintf(logfd, "Tried mounting with source = %s\n", source);
+        close(logfd);
+        exit(1);
+    }
+}
+
+void check_target(char *target) {
+    target[arg_length-1]='\0';
+    if (strstr(target,"..")) {
+        fprintf(logfd,"Tried mounting with target = %s\n", target);
+        close(logfd);
+        exit(1);
+    }
+}
+
+void check_fstype(char *filesystemtype) {
+    if (strncmp(filesystemtype,"fuse",4)) {
+        fprintf(logfd,"Tried mounting filesystem type %s\n", filesystemtype);
+        close(logfd);
+        exit(1);
+    }
+}
+
+int main(int argc, char *argv[]) {
+    int control_channel_fd, magic_fd, mount_fd;
+    char source[128],target[128],filesystemtype[128],data[128],slice_target[1024];
+
+    int received;
+
+    if (argc < 3) {
+        printf("This script is called by vsys.\n");
+        exit(1);
+    }
+
+    char *slice_name = argv[1];
+
+    logfd=fopen("/tmp/fuselog","w");
+    if (!logfd) {logfd = stderr;}
+    
+    sscanf(argv[2],"%d", &control_channel_fd);
+
+    if (control_channel_fd <3 || control_channel_fd > 1023) {
+        printf ("Got control_channel_fd = %d\n", control_channel_fd);
+        exit(1);
+    }
+
+    receive_argument(control_channel_fd, source);
+    receive_argument(control_channel_fd, target);
+    receive_argument(control_channel_fd, filesystemtype);
+    receive_argument(control_channel_fd, data);
+
+    mount_fd = receive_fd (control_channel_fd);
+
+    if (mount_fd < 2) {
+        printf("mount_fd = %d\n", mount_fd);
+        exit(1);
+    }
+
+    set_magic_fd(data, mount_fd);
+
+
+    check_source(source);
+    check_target(target);
+    check_fstype(filesystemtype);
+
+    sprintf(slice_target,"/vservers/%s/%s", slice_name, target);
+
+    fprintf(logfd, "Mount fd: %d Source: %s slice_target: %s fstype: %s mountflags: %d data: %s\n", mount_fd, source, slice_target, filesystemtype, mountflags, data);
+
+    if (!mount(source, slice_target, filesystemtype, mountflags, data)) {
+        send_fd(control_channel_fd, mount_fd);
+    }
+    else {
+        printf ("Error executing mount\n");
+        exit(1);
+    }
+
+    close(logfd);
+    return 0;
+}
diff --git a/fd_tos.c b/fd_tos.c
new file mode 100644 (file)
index 0000000..970bafa
--- /dev/null
+++ b/fd_tos.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#include "fdpass.h"
+
+/*
+ * Definitions for IP type of service
+ */
+#define IPTOS_LOWDELAY    0x10
+#define IPTOS_THROUGHPUT  0x08
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_MINCOST     0x02
+#define IPTOS_NORMALSVC   0x00
+
+static void receive_argument(int control_fd, int *TOS_value)
+{
+    if (recv(control_fd, TOS_value, sizeof(int), 0) != sizeof(int)) {
+        fprintf(stderr, "receiving the IP_TOS argument failed\n");
+        exit(-1);
+    }
+}
+
+int main(int argc, char *argv[]) 
+{
+    int control_channel_fd, magic_socket;
+    int TOS_value = IPTOS_NORMALSVC;
+    if (argc < 3) {
+        printf("This script is called by vsys.\n");
+        exit(1);
+    }
+
+    control_channel_fd = atoi(argv[2]);  
+    
+    /* receive IP_TOS paramater */
+    receive_argument(control_channel_fd, &TOS_value);
+
+    switch (TOS_value)
+    {
+        case IPTOS_NORMALSVC:
+        case IPTOS_MINCOST:
+        case IPTOS_RELIABILITY:
+        case IPTOS_THROUGHPUT:
+        case IPTOS_LOWDELAY:
+           break;
+        default:
+            fprintf(stderr, "IP_TOS value not known: %d\n", errno);
+            exit(1);
+    }
+
+    magic_socket =  receive_fd(control_channel_fd);
+    if (magic_socket == -1) { 
+        fprintf(stderr, "Error creating socket: %d\n", errno);
+        exit(1);
+    }
+
+    if (setsockopt(magic_socket, IPPROTO_IP, IP_TOS, &TOS_value, sizeof(TOS_value)) < 0 ) {
+        fprintf(stderr, "Error calling setsockopt for IPPROTO_IP: %d\n", errno);
+        exit(1);
+    }
+
+    send_fd(control_channel_fd, magic_socket);
+}
diff --git a/fd_tuntap.c b/fd_tuntap.c
new file mode 100644 (file)
index 0000000..45e66be
--- /dev/null
@@ -0,0 +1,135 @@
+/* fd_tuntap.c: VSYS script to allocate slice-local tuntap interfaces.
+ *   Thom Haddow - 06/09/09
+ *
+ * Reads interface type from local control unix socket, replies with fd for new
+ * (unconfigured) tuntap interface. VSYS client can get interface name with
+ * TUNGETIFF ioctl. 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pwd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+int send_vif_fd(int sock_fd, int vif_fd, char *vif_name)
+{
+       int retval;
+       struct msghdr msg;
+       struct cmsghdr *p_cmsg;
+       struct iovec vec;
+       size_t cmsgbuf[CMSG_SPACE(sizeof(vif_fd)) / sizeof(size_t)];
+       int *p_fds;
+
+
+       msg.msg_control = cmsgbuf;
+       msg.msg_controllen = sizeof(cmsgbuf);
+       p_cmsg = CMSG_FIRSTHDR(&msg);
+       p_cmsg->cmsg_level = SOL_SOCKET;
+       p_cmsg->cmsg_type = SCM_RIGHTS;
+       p_cmsg->cmsg_len = CMSG_LEN(sizeof(vif_fd));
+       p_fds = (int *) CMSG_DATA(p_cmsg);
+       *p_fds = vif_fd;
+       msg.msg_controllen = p_cmsg->cmsg_len;
+       msg.msg_name = NULL;
+       msg.msg_namelen = 0;
+       msg.msg_iov = &vec;
+       msg.msg_iovlen = 1;
+       msg.msg_flags = 0;
+
+    /* Send the interface name as the iov */
+       vec.iov_base = vif_name;
+       vec.iov_len = strlen(vif_name)+1;
+
+       while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+       if (retval != 1) {
+               perror("sending file descriptor");
+               return -1;
+       }
+       return 0;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+    int control_channel_fd;
+    int tap_fd;
+    int slice_uid;
+    char if_name[IFNAMSIZ];
+    int if_type;
+    struct ifreq ifr;
+    struct passwd *pwd;
+   
+    if(argc < 3) {
+        printf("This script is called by vsys.\n");
+        exit(-1);
+    }
+
+
+    /* Get slice UID and control channel fd from VSYS args */ 
+    pwd = getpwnam(argv[1]);
+    if(pwd==NULL) {
+        perror("Failed to lookup UID");
+        exit(-1);
+    }
+    slice_uid = pwd->pw_uid;
+    sscanf(argv[2],"%d", &control_channel_fd);
+
+   
+     
+    /* Get type param from control channel. */
+    if(recv(control_channel_fd, &if_type, sizeof(int), 0) != sizeof(int)) {
+        perror("fd_tuntap: Failed to read from control channel");
+        exit(-1);
+    }
+    
+   
+    /* Generate basename for interface */
+    if(if_type==IFF_TUN) {
+        sprintf(if_name, "tun%d-%%d", slice_uid);
+    }
+    else if(if_type==IFF_TAP) {
+        sprintf(if_name, "tap%d-%%d", slice_uid);
+    }
+    else { /* TODO: Might also want to allow the other types? */
+        fprintf(stderr, "fd_tuntap: %d is not a valid interface type",if_type);
+        exit(-1); 
+    }
+
+    /* Open tun device */
+    if( (tap_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
+        system("modprobe tun");
+        if( (tap_fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
+            perror("ERROR: tun_alloc():open(/dev/net/tun)");
+            exit(-1);
+        }
+    }
+
+
+    /* Set interface type */
+    memset(&ifr, 0, sizeof(ifr));
+    ifr.ifr_flags = if_type; 
+    strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
+    
+    if( ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0 ) {
+        close(tap_fd);
+        perror("fd_tuntap: Failed to set tun type");
+    }
+
+    /* Read initialised interface name */
+    strcpy(if_name, ifr.ifr_name);
+
+
+    /* Send tap_fd to slice */
+    send_vif_fd(control_channel_fd, tap_fd, if_name);
+
+    return 0;
+}
diff --git a/fd_udpsocket.c b/fd_udpsocket.c
new file mode 100644 (file)
index 0000000..8fa6651
--- /dev/null
@@ -0,0 +1,75 @@
+/* Copy of fd_bmsocket.c that creates UDP sockets instead of TCP sockets. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "fdpass.h"
+
+#define MAX_BUFSIZE (32*1024*1024)
+
+/*------------------------------------------------------------------*/
+void
+receive_argument(int control_fd, int *rcvbuf, int *sndbuf)
+{
+  if (recv(control_fd, rcvbuf, sizeof(int), 0) != sizeof(int)) {
+    fprintf(stderr, "receiving the first argument failed\n");
+    exit(-1);
+  }
+  if (recv(control_fd, sndbuf, sizeof(int), 0) != sizeof(int)) {
+    fprintf(stderr, "receiving the first argument failed\n");
+    exit(-1);
+  }
+}
+/*------------------------------------------------------------------*/
+int 
+main(int argc, char *argv[]) 
+{
+    int control_channel_fd, magic_socket;
+    int rcvbufsize = 0, sndbufsize = 0;
+    
+    if (argc < 3) {
+        printf("This script is called by vsys.\n");
+        exit(1);
+    }
+
+    sscanf(argv[2],"%d", &control_channel_fd);
+
+    /* receive paramaters: rcvbufsize and sndbufsize */
+    receive_argument(control_channel_fd, &rcvbufsize, &sndbufsize);
+    if (rcvbufsize > MAX_BUFSIZE)
+      rcvbufsize = MAX_BUFSIZE;
+    if (sndbufsize > MAX_BUFSIZE)
+      sndbufsize = MAX_BUFSIZE;
+
+    magic_socket = socket(AF_INET, SOCK_DGRAM, 0);
+    if (magic_socket == -1) {
+      fprintf(stderr, "Error creating socket: %d\n", errno);
+      exit(1);
+    }
+
+    /* buffer size <= 0 means we should ignore the parameter */
+    if (rcvbufsize > 0) {
+      if (setsockopt(magic_socket, 
+                    SOL_SOCKET, 
+                    SO_RCVBUFFORCE, 
+                    &rcvbufsize, sizeof(unsigned int))) {
+        fprintf(stderr, "Error calling setsockopt for RCVBUFFORCE: %d\n", 
+               errno);
+        exit(1);
+      }
+    }
+    if (sndbufsize > 0) {
+      if (setsockopt(magic_socket, 
+                    SOL_SOCKET, 
+                    SO_SNDBUFFORCE, 
+                    &sndbufsize, sizeof(unsigned int))) {
+        fprintf(stderr, "Error calling setsockopt for SNDBUFFORCE: %d\n", 
+               errno);
+        exit(1);
+      }
+    }
+
+    send_fd(control_channel_fd, magic_socket);
+}
diff --git a/fdpass.c b/fdpass.c
new file mode 100644 (file)
index 0000000..5548064
--- /dev/null
+++ b/fdpass.c
@@ -0,0 +1,93 @@
+// Modified version of library functions in FUSE
+//
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+int send_fd(int sock_fd, int fd)
+{
+       int retval;
+       struct msghdr msg;
+       struct cmsghdr *p_cmsg;
+       struct iovec vec;
+       size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
+       int *p_fds;
+       char sendchar = 0;
+
+       msg.msg_control = cmsgbuf;
+       msg.msg_controllen = sizeof(cmsgbuf);
+       p_cmsg = CMSG_FIRSTHDR(&msg);
+       p_cmsg->cmsg_level = SOL_SOCKET;
+       p_cmsg->cmsg_type = SCM_RIGHTS;
+       p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+       p_fds = (int *) CMSG_DATA(p_cmsg);
+       *p_fds = fd;
+       msg.msg_controllen = p_cmsg->cmsg_len;
+       msg.msg_name = NULL;
+       msg.msg_namelen = 0;
+       msg.msg_iov = &vec;
+       msg.msg_iovlen = 1;
+       msg.msg_flags = 0;
+       /* "To pass file descriptors or credentials you need to send/read at
+        * least one byte" (man 7 unix) */
+       vec.iov_base = &sendchar;
+       vec.iov_len = sizeof(sendchar);
+       while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+       if (retval != 1) {
+               perror("sending file descriptor");
+               return -1;
+       }
+       return 0;
+}
+
+
+/* return value:
+ * >= 0         => fd
+ * -1   => error
+ */
+int receive_fd(int fd)
+{
+       struct msghdr msg;
+       struct iovec iov;
+       char buf[1];
+       int rv;
+       size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
+       struct cmsghdr *cmsg;
+
+       iov.iov_base = buf;
+       iov.iov_len = 1;
+
+       msg.msg_name = 0;
+       msg.msg_namelen = 0;
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+       /* old BSD implementations should use msg_accrights instead of
+        * msg_control; the interface is different. */
+       msg.msg_control = ccmsg;
+       msg.msg_controllen = sizeof(ccmsg);
+
+       while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
+       if (rv == -1) {
+               perror("recvmsg");
+               return -1;
+       }
+       if(!rv) {
+               /* EOF */
+               return -1;
+       }
+
+       cmsg = CMSG_FIRSTHDR(&msg);
+       if (!cmsg->cmsg_type == SCM_RIGHTS) {
+               fprintf(stderr, "got control message of unknown type %d\n",
+                       cmsg->cmsg_type);
+               return -1;
+       }
+       return *(int*)CMSG_DATA(cmsg);
+}
+
diff --git a/fdpass.h b/fdpass.h
new file mode 100644 (file)
index 0000000..f00a6fb
--- /dev/null
+++ b/fdpass.h
@@ -0,0 +1,5 @@
+// Modified version of library functions in FUSE
+//
+int send_fd(int sock_fd, int fd);
+int receive_fd(int fd);
+
diff --git a/support/tun_test.c b/support/tun_test.c
new file mode 100644 (file)
index 0000000..947019f
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include "tunalloc.h"
+
+int main(void)
+{
+    printf("Allocating tap device via VSYS\n");
+
+    char if_name[IFNAMSIZ];
+
+    int tun_fd = tun_alloc(IFF_TAP, if_name);
+
+    printf("Allocated tap device: %s fd=%d\n", if_name, tun_fd);
+
+    printf("Sleeping for 120 secs...\n");
+
+    sleep(120);
+
+    printf("Closing\n");
+
+    return 0;
+}
diff --git a/support/tunalloc.c b/support/tunalloc.c
new file mode 100644 (file)
index 0000000..6adcf24
--- /dev/null
@@ -0,0 +1,95 @@
+/* Slice-side code to allocate tuntap interface in root slice
+ * Based on bmsocket.c
+ *  Thom Haddow - 08/10/09
+ *
+ * Call tun_alloc() with IFFTUN or IFFTAP as an argument to get back fd to
+ * new tuntap interface. Interface name can be acquired via TUNGETIFF ioctl.
+ */
+
+#include <sys/un.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#define VSYS_TUNTAP "/vsys/fd_tuntap.control"
+
+/* Reads vif FD from "fd", writes interface name to vif_name, and returns vif FD.
+ * vif_name should be IFNAMSIZ chars long. */
+int receive_vif_fd(int fd, char *vif_name)
+{
+       struct msghdr msg;
+       struct iovec iov;
+       int rv;
+       size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
+       struct cmsghdr *cmsg;
+
+    /* Use IOV to read interface name */
+       iov.iov_base = vif_name;
+       iov.iov_len = IFNAMSIZ;
+
+       msg.msg_name = 0;
+       msg.msg_namelen = 0;
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+       /* old BSD implementations should use msg_accrights instead of
+        * msg_control; the interface is different. */
+       msg.msg_control = ccmsg;
+       msg.msg_controllen = sizeof(ccmsg);
+
+       while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
+       if (rv == -1) {
+               perror("recvmsg");
+               return -1;
+       }
+       if(!rv) {
+               /* EOF */
+               return -1;
+       }
+
+       cmsg = CMSG_FIRSTHDR(&msg);
+       if (!cmsg->cmsg_type == SCM_RIGHTS) {
+               fprintf(stderr, "got control message of unknown type %d\n",
+                       cmsg->cmsg_type);
+               return -1;
+       }
+       return *(int*)CMSG_DATA(cmsg);
+}
+
+
+int tun_alloc(int iftype, char *if_name)
+{
+    int control_fd;
+    struct sockaddr_un addr;
+    int remotefd;
+
+    control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (control_fd == -1) {
+        perror("Could not create UNIX socket\n");
+        exit(-1);
+    }
+
+    memset(&addr, 0, sizeof(struct sockaddr_un));
+    /* Clear structure */
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, VSYS_TUNTAP,
+            sizeof(addr.sun_path) - 1);
+
+    if (connect(control_fd, (struct sockaddr *) &addr,
+                sizeof(struct sockaddr_un)) == -1) {
+        perror("Could not connect to Vsys control socket");
+        exit(-1);
+    }
+
+    /* passing type param */
+    if (send(control_fd, &iftype, sizeof(iftype), 0) != sizeof(iftype)) {
+        perror("Could not send paramater to Vsys control socket");
+        exit(-1);
+    }
+
+    remotefd = receive_vif_fd(control_fd, if_name);
+    return remotefd;
+}
diff --git a/support/tunalloc.h b/support/tunalloc.h
new file mode 100644 (file)
index 0000000..3e5caae
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TUNALLOC_H
+#define _TUNALLOC_H
+
+int tun_alloc(int iftype, char *if_name);
+
+#endif
diff --git a/svn-commit.tmp b/svn-commit.tmp
deleted file mode 100644 (file)
index d04acbe..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-First checkin. Vsys scripts will live here in the future.
-
---This line, and those below, will be ignored--
-
-A    vsys-factory
diff --git a/vsys-factory.spec b/vsys-factory.spec
deleted file mode 100644 (file)
index 8aec52b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Vsys filesystem
-#
-# RPM spec file
-#
-# $Id: vsys-factory.spec 9786 2008-07-02 08:54:09Z thierry $
-#
-
-%define name vsys-factory
-%define version 0.7
-%define taglevel 0
-
-%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
-
-Vendor: PlanetLab
-Packager: PlanetLab Central <support@planet-lab.org>
-Distribution: PlanetLab %{plrelease}
-URL: %(echo %{url} | cut -d ' ' -f 2)
-
-Summary: Vsys factory scripts
-Name: %{name}
-Version: %{version}
-Release: %{release}
-License: GPL
-Group: System Environment/Kernel
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
-Requires: vsys
-
-Source0: vsys-factory-%{version}.tar.gz
-
-%description
-Vsys scripts for privileged operations on PlanetLab. These scripts are defined by maintainers of various components,
-to which users require privileged access.
-
-%prep
-%setup
-
-%build
-rm -rf $RPM_BUILD_ROOT
-make
-
-%install
-mkdir -p $RPM_BUILD_ROOT/vsys
-cp exec/* $RPM_BUILD_ROOT/vsys
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-/vsys/*
-
-%post
-
-%postun
-
-%changelog
-
index 13e5393..edc8959 100644 (file)
@@ -3,10 +3,10 @@
 #
 # RPM spec file
 #
-# $Id: vsys.spec 9786 2008-07-02 08:54:09Z thierry $
+# $Id$
 #
 
-%define url $URL: svn+ssh://sapanb@poppins/svn/vsys/trunk/vsys.spec $
+%define url $URL$
 
 %define name vsys
 %define version 0.8
diff --git a/vsys-scripts.spec b/vsys-scripts.spec
new file mode 100644 (file)
index 0000000..12bfaf1
--- /dev/null
@@ -0,0 +1,124 @@
+#
+# Vsys filesystem
+#
+# RPM spec file
+#
+# $Id$
+#
+
+%define name vsys-scripts
+%define version 0.95
+%define taglevel 19
+
+%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+
+Vendor: PlanetLab
+Packager: PlanetLab Central <support@planet-lab.org>
+Distribution: PlanetLab %{plrelease}
+URL: %(echo %{url} | cut -d ' ' -f 2)
+
+Summary: Vsys scripts scripts
+Name: %{name}
+Version: %{version}
+Release: %{release}
+License: GPL
+Group: System Environment/Kernel
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+Requires: vsys
+
+Source0: vsys-scripts-%{version}.tar.gz
+
+%description
+Vsys scripts for privileged operations on PlanetLab. These scripts are defined by maintainers of various components,
+to which users require privileged access.
+
+%prep
+%setup
+
+%build
+rm -rf $RPM_BUILD_ROOT
+make
+
+%install
+mkdir -p $RPM_BUILD_ROOT/vsys
+cp exec/* $RPM_BUILD_ROOT/vsys
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+/vsys/*
+
+%post
+
+%postun
+
+%changelog
+* Thu Jul 01 2010 Baris Metin <Talip-Baris.Metin@sophia.inria.fr> - vsys-scripts-0.95-19
+- change dotsshmount's mount point
+
+* Fri Jun 25 2010 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-18
+- Switch fd_tuntap to 2.6.27.
+
+* Fri Apr 30 2010 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-17
+- Tweak to if_port_forward script.
+
+* Fri Apr 30 2010 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-16
+- Added if_port_forward script to enable slices to forward ports for their
+- allocated IP addresses.
+
+* Wed Mar 03 2010 Talip Baris Metin <Talip-Baris.Metin@sophia.inria.fr> - vsys-scripts-0.95-15
+- - hostname filter and updated documentation for ipfw scripts - Marta
+- - vsys script for letting users to set the Type of Services(ToS) byte in the IPv4 header - Caglar
+- (if this is not needed anymore please remove and tag again)
+
+* Thu Jan 21 2010 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-14
+- Tweak to Thom Haddow's script to let a slice see packets related to
+- existing connections.
+
+* Mon Jan 11 2010 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-scripts-0.95-13
+- ipfw frontend has a rules cleanup feature
+- ongoing work around vif_up
+- new script 'run_with_devices'
+
+* Thu Nov 26 2009 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-scripts-0.95-12
+- improve usability of the ipfw backend
+
+* Wed Oct 28 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-11
+- * Load the tun module if it is not already loaded
+- * Fixed a bug in fd_tuntap
+
+* Tue Oct 27 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-10
+- Adds Thom Haddow's tun/tap changes. I omitted a change in my previous commit.
+
+* Tue Oct 27 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-9
+- This update adds Thom Haddow's custom tun/tap-device scripts.
+
+* Wed Sep 09 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - vsys-scripts-0.95-8
+- Added script to create UDP sockets instead of TCP sockets w/ big buffers
+
+* Mon Sep 07 2009 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-scripts-0.95-7
+- minor changes in sliceip and ipfw, new reserve_udp_port
+
+* Mon Aug 03 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-6
+- Added reserve_tcp_port and Giovanni's slice_ip tool.
+
+* Tue Jul 07 2009 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-scripts-0.95-5
+- tweak in ipfw-be for in-node emulation
+
+* Thu Jun 11 2009 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - vsys-scripts-0.95-4
+- Added the ipfw backend script
+
+* Fri Jun 05 2009 Faiyaz Ahmed <faiyaza@cs.princeton.edu> - vsys-scripts-0.95-3
+- rsync authlogs to ~/
+
+* Mon May 18 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-2
+- Security update. umount had an issue that might have been exploited.
+
+* Thu May 14 2009 Sapan Bhatia <sapanb@cs.princeton.edu> - vsys-scripts-0.95-1
+- Adding port reservation script (goodfences)
+- Modifying umount to be more (or less, depending on your point of view) robust
+
+
+
+%define module_current_branch 0.7