DBFILE=/tmp/ff
lockfile=/var/lock/ipfw.lock
-# These values are the keys used in the database for blocks,
-# rules and pipes
-# The index rule numbers allocated to a slice can be computed
-# with the following formula:
-# index_min_rule = $(($RULE_BASE + $(($M*$block_n))))
-# where block_n is the block number associated with the slice
-# and M is the block size.
+# These values are the keys used in the database for blocks
+# and pipes. For rules we store directly the ipfw number.
+#
+# For each user we allocate a block of $M rules. The rules
+# allocated to users are within the range:
+# ipfw_min_rule = RULE_BASE
+# ipfw_max_rule = RULE_BASE + ((M-1)*block_n) -1
BLOCK_MIN=1
BLOCK_MAX=1000
M=50 # block size
-RULE_BASE=10001 # the hightest rule is RULE_BASE + (M*BLOCK_MAX)
PIPE_MIN=1
PIPE_MAX=25000
+
# These are the actual rule numbers used in ipfw
IPFW_RULE_MIN=10000
-IPFW_RULE_MAX=59999
IPFW_PIPE_MIN=10000
-IPFW_PIPE_MAX=59999
-# The mapping between keys and ipfw configuration number follow:
-# rule_nr 10001..20000 are mapped to ipfw_rules 50000..59999 (n+39999)
-# pipe_nr 1..25000 are mapped to ipfw_pipes 10000-59999 (n*2+9998)
-# Rule index can be mapped to ipfw rules with the following formula:
-# ipfw_rule = $(($index_rule + 39999))
-# Pipes index can be mapped to ipfw pipes with:
-# ipfw_pipein = $(($index_pipe + $index_pipe + 9998))
-# ipfw_pipeout = $(($ipfw_pipein + $1))
-#
-# the skipto and the generic default rule
+
+# 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
# set slicename and slice_id
# these are the credential of the user invoking the backend
SLICENAME=$1
-if [ $SLICENAME = 0 ]; then
- SLICE_ID=0
-else
- SLICE_ID=`id -u $SLICENAME`
-fi
+SLICE_ID=`id -u $SLICENAME`
+[ x"$SLICE_ID" = x"" ] && echo "No sliver present." && exit
# programs
# XXX check consistency for variables {}
# is not supported so for the time being we kill them all
${IPFW} -q flush
${IPFW} -q pipe flush
- # ${IPFW} delete ${IPFW_RULE_MIN}-${IPFW_RULE_MAX}
- # ${IPFW} pipe delete ${IPFW_PIPE_MIN}-${IPFW_PIPE_MAX}
+ ${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
# CONFIG_IN CONFIG_OUT because they may be long.
# Other arguments are on the command line
-add_rule() { # new_rule type arg rule pipe_base timeout
- local new_rule=$1 type=$2 arg=$3
- local rule_base=$4 pipe_base=$5 timeout=$6
- local pipe_in pipe_out rule_in rule_out check_timeout
+#
+# 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
# If we use a profile file, locate the user directory
# move in the slice root dir XXX todo
- [ "$TEST" != "1" ] && cd /vservers/${SLICENAME}/root
+ # [ "$TEST" != "1" ] && cd /vservers/${SLICENAME}/root
#echo ${CONFIG_STRING} | ${SED} -e "s/ profile \(.[^ ]\)/ profile \/vservers\/${SLICENAME}\/\1/g"
+ # find actual pipe numbers
+ ipfw_pipe_in=$(($IPFW_PIPE_MIN + $((2 * $(($pipe_index - 1)))) ))
+ ipfw_pipe_out=$(($ipfw_pipe_in + 1))
+ local del # used delete incompatible configurations
+
# first, call ipfw -n to check syntax, if ok move on and do the action
- pipe_in=$(($pipe_base + $pipe_base + 9998))
- pipe_out=$(($pipe_in + 1))
- local del # anything to delete ?
- local rule_nr=$(($rule_base + 39999)) # formula for individual rules
if [ x"$new_rule" != x"0" ] ; then
case $type in
server)
;;
esac
- rule_in="pipe ${pipe_in} in jail $SLICE_ID ${rule_in} // $type $arg"
- rule_out="pipe ${pipe_out} out jail $SLICE_ID ${rule_out} // $type $arg"
- ${IPFW_CHECK} add ${rule_nr} $rule_in > /dev/null || \
+ rule_in="pipe ${ipfw_pipe_in} in jail $slice_id ${rule_in} // $type $arg"
+ rule_out="pipe ${ipfw_pipe_out} out jail $slice_id ${rule_out} // $type $arg"
+
+ ${IPFW_CHECK} add ${ipfw_rule} $rule_in > /dev/null || \
abort "ipfw syntax error $rule_in"
- ${IPFW_CHECK} add ${rule_nr} $rule_out > /dev/null || \
+ ${IPFW_CHECK} add ${ipfw_rule} $rule_out > /dev/null || \
abort "ipfw syntax error $rule_out"
fi
# check error reporting
- ${IPFW_CHECK} pipe ${pipe_in} config ${CONFIG_PIPE_IN} > /dev/null || \
+ ${IPFW_CHECK} pipe ${ipfw_pipe_in} config ${CONFIG_PIPE_IN} > /dev/null || \
abort "ipfw syntax error pipe_in"
- ${IPFW_CHECK} pipe ${pipe_out} config ${CONFIG_PIPE_OUT} > /dev/null || \
+ ${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 $SLICE_ID service $arg
- [ "$del" = "cli_ser" ] && do_delete $SLICE_ID client $arg
- [ "$del" = "cli_ser" ] && do_delete $SLICE_ID server $arg
- [ "$new_rule" != "0" ] && ${IPFW} add ${rule_nr} $rule_in > /dev/null
- [ "$new_rule" != "0" ] && ${IPFW} add ${rule_nr} $rule_out > /dev/null
+ [ "$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
- ${IPFW} pipe ${pipe_in} config ${CONFIG_PIPE_IN}
- ${IPFW} pipe ${pipe_out} config ${CONFIG_PIPE_OUT}
+ ${IPFW} pipe ${ipfw_pipe_in} config ${CONFIG_PIPE_IN}
+ ${IPFW} pipe ${ipfw_pipe_out} config ${CONFIG_PIPE_OUT}
# send output to the user
- ${IPFW} show ${rule_nr}
- ${IPFW} pipe ${pipe_in} show
- ${IPFW} pipe ${pipe_out} show
+ ${IPFW} show ${ipfw_rule}
+ ${IPFW} pipe ${ipfw_pipe_in} show
+ ${IPFW} pipe ${ipfw_pipe_out} show
+#add test
[ "$TEST" = "1" ] && return
# add to the database
- ( grep -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE; \
- echo "${SLICE_ID} ${type} ${arg} ${rule_base} ${pipe_base} ${timeout}" ) > ${DBFILE}.tmp
+ ( grep -v -- "^${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
-do_delete() { # type arg
- local pipe_in pipe_out pipe_base rule_base rule_nr
- local type=$1 arg=$2
+# 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 {SERVICE|SERVER|CLIENT} port_number"
- set `find_rule $SLICE_ID $type $arg`
- rule_base=$1; pipe_base=$2
- [ "$rule_base" = "0" ] && return # no rules found
-
- rule_nr=$(($rule_base + 39999)) # XXX only individual rules
- pipe_in=$(($pipe_base + $pipe_base + 9998))
- pipe_out=$(($pipe_in + 1))
-
- $IPFW delete ${rule_nr}
- $IPFW pipe delete ${pipe_in}
- $IPFW pipe delete ${pipe_out}
- echo "removed configuration ${SLICE_ID} ${type} ${arg}"
- [ "$TEST" = "1" ] && return
+ 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
- grep -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE > ${DBFILE}.tmp
+ grep -v -- "^${slice_id} ${type} ${arg} " $DBFILE > ${DBFILE}.tmp
mv ${DBFILE}.tmp ${DBFILE}
- # XXX if the use block is empty
+ # if there are no mor rules for the user
# remove the table entry from ipfw and from the db
- # not yet implemented
+ [ $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`
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 -v -- "^${slice_id} BLOCK ${block_n}" $DBFILE; ) > ${DBFILE}.tmp
+ mv ${DBFILE}.tmp ${DBFILE}
+ return 0
+}
+
+#
+# find a rule and pipes
+# allocate a new block if no rules are found.
+#
+# Return ipfw_rule, index_pipe and new_rule
+# new_rule is a flag set if the rule was not found
+#
+# return 0 as first argument if there are no resource 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 allocated block
+ # if not found, allocate a new block
+ local block_n=`find_block ${slice_id}`
+ [ ${block_n} = "0" ] && new_block=1 && block_n=`allocate_block`
+ [ ${block_n} = "0" -o ${block_n} -gt $BLOCK_MAX ] && echo 0 && return 0;
+
+ # here we have a valid block id
+ # compute the user block ruleset
+ local ipfw_rulemin=$(($IPFW_RULE_MIN + $(($M *$(($block_n - 1))))))
+ local ipfw_rulemax=$(($(($ipfw_rulemin + $M)) - 1 ))
+
+ # find rule and pipes, we reserve the last rule to the user default rule
+ set `allocate_resources $ipfw_rulemin $(($ipfw_rulemax - 1))`
+ ipfw_rule=$1; pipe_index=$2
+ [ $ipfw_rule = 0 ] && echo 0 && return 0 # no resources
+
+ # configure the table, add the last user rule and update the database
+ 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 rule_base pipe_base timeout
-# On match returns <rule_base pipe_base timeout>
+# slice_id type arg ipfw_rule pipe_index timeout
+# On match returns <ipfw_rule pipe_index timeout>
# On non match returns 0 0 0
-find_rule() { # $1 slice_id $2 type $3 arg
+# no echo inside
+find_rule() { # slice_id type arg
local ret
- ret=`grep -- "^$1 $2 $3 " $DBFILE`
+ ret=`grep -- "^$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
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
echo $cand
}
+#
# returns a free rule and pipe base for client|server|service
# within a block
# Returns r=0 if there are no resources available
-allocate_resources() {
+# 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 | \
echo $r $p
}
+#
+# allocate a free block
+# Returns 0 if there are no resources available
+# no debug inside
+allocate_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:
dbcleanup)
clean_db; return 0
;;
+ killexpired)
+ kill_expired; return 0
+ ;;
*)
abort "Invalid super command"
;;
esac
}
-#
-# show ipfw rules and pipes filtering on slice_id
-# If the first argument is 0 filter rules,
-# otherwise filter pipes
-do_show() { #$1 show rules or pipes
- local list ipfw_list
-
- if [ $1 == "0" ]; then
- list=`grep "^$SLICE_ID " $DBFILE | grep -v BLOCK | cut -d " " -f 4`
- for i in $list; do ipfw_list="$ipfw_list $(($i + 39999))"; done
- [ -n "${ipfw_list}" ] && ${IPFW} show $ipfw_list
- else
- # ipfw pipe show does not selectively filter pipes
- # XXX so leave this code commented and show all pipes
- #list=`grep "^$SLICE_ID " $DBFILE | grep -v BLOCK | cut -d " " -f 5`
- # the pipe list is build adding two ipfw pipes for each pipe index
- #for i in $list; do ipfw_list="$ipfw_list $(($i + $i + 9998)) $(($i + $i + 9998 +1)) "; done
- #[ -n "${ipfw_list}" ] && ${IPFW} pipe show $ipfw_list
- ${IPFW} pipe show
- fi
-}
-
#
# refresh the rule timeout
-do_refresh() { # type arg timeout
- local pipe_in pipe_out pipe_base rule_base rule_nr
- local type=$1 arg=$2 timeout=$3
+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`
- rule_base=$1; pipe_base=$2
- [ "${rule_base}" = "0" ] && debug "no rules found" && return 0 # no rules found
-
- rule_nr=$(($rule_base + 39999)) # XXX only individual rules
- pipe_in=$(($pipe_base + $pipe_base + 9998))
- pipe_out=$(($pipe_in + 1))
- debug "ipfw rule and pipes value: rule: <$rule_nr> pipe in: <$pipe_in> pipe_out: <$pipe_out>"
+ 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 -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE; \
- echo "${SLICE_ID} ${type} ${arg} ${rule_base} ${pipe_base} ${timeout}" ) > ${DBFILE}.tmp
+ ( grep -v -- "^${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] PIPE_IN <pipe_conf> PIPE_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.
process() {
local new_pipe=0
local timeout TMP i rule_base pipe_base
- local slicename=${SLICENAME}
local cmd=$1 ; shift
local debug_args="$*";
local type=$1 ; shift
# 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 user define timeout value
+ # 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 //'`
- check_timeout ${timeout} # abort on error
+ 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
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")
- [ "$type" = "server" ] && do_config $timeout $type $args && return 0
- [ "$type" = "client" ] && do_config $timeout $type $args && return 0
- [ "$type" = "service" ] && do_config $timeout $type $args && return 0
+ [ "$type" = "server" ] && do_config $SLICE_ID $timeout $type $args && return 0
+ [ "$type" = "client" ] && do_config $SLICE_ID $timeout $type $args && return 0
+ [ "$type" = "service" ] && do_config $SLICE_ID $timeout $type $args && return 0
abort "'config' should be followed by {server|client|service}"
;;
x"delete")
- do_delete ${SLICE_ID} $type $args
+ do_delete 1 $SLICE_ID $type $args
;;
x"refresh")
- do_refresh $type $args $timeout && return 0
+ do_refresh $SLICE_ID $type $args $timeout && return 0
;;
x"show")
- [ "$type" = "rules" ] && do_show 0 && return 0
- [ "$type" = "pipes" ] && do_show 1 && return 0
+ # 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")
# validate the timeout
check_timeout() { # timeout
local tt=`date --date="${1}" +%s`
- [ "$?" != "0" ] && abort "Date format $1 not valid"
+ [ "$?" != "0" ] && echo 0 && return
+ echo $tt
}
-do_config() { # timeout type arg PIPE_IN pipe_conf PIPE_OUT pipe_conf
+do_config() { # slice_id timeout type arg PIPE_IN pipe_conf PIPE_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
debug "-----------------------"
# check if the link is already configured
- debug "Search for ${SLICE_ID} ${type} ${arg}"
-
- set `find_rule ${SLICE_ID} ${type} ${arg}`
- local rule_base=$1
- local pipe_base=$2
- local new_pipe=0
-
- if [ ! ${rule_base} = "0" ] ; then
- debug "Rule found, just changing the pipe configuration"
- add_rule $new_pipe $type $arg $rule_base $pipe_base $timeout
- hook_call $type $port $rule_base $pipe_base $timeout
- return 0; # link configured, exit
- fi
-
- debug "link not found, search for a block already allocated to the user"
-
- # Search if there is a block already allocated to the slice_id
- set `find_block ${SLICE_ID}`
- local block_n=$1
- if [ ${block_n} = "0" ] ; then
- debug "Block not found, allocate a new block"
- # blocks are allocated in sequence, get the first free
- block_n=`grep BLOCK $DBFILE | tail -1 | cut -d " " -f 3`
- if [ -z $block_n ]; then
- block_n=$(($BLOCK_MIN - 1))
- fi
- RULE_IN_MIN=$(($RULE_BASE + $(($M*$block_n))))
- block_n=$(($block_n +1))
- debug "Allocated new block $block_nr to user $SLICE_ID"
- [ $block_n -gt $BLOCK_MAX ] && abort "no block resources available"
-
- # add the rule into the firewall table.
- # note that the rule number into the table are not database number,
- # so we need to compute the firewall number before the table insertion
- local ipfw_rule_nr=$(($RULE_IN_MIN + 39999)) # XXX formula for individual rules
- debug "Configuring table: <${IPFW_CHECK} table $SLICE_TABLE add ${SLICE_ID} ${ipfw_rule_nr}>"
- ${IPFW_CHECK} table $SLICE_TABLE add ${SLICE_ID} ${rule_nr} > /dev/null || \
- abort "ipfw syntax error $rule_out"
- ${IPFW} table $SLICE_TABLE add ${SLICE_ID} ${ipfw_rule_nr} > /dev/null
-
- [ "$TEST" = "1" ] && return
- # add the block declaration to the database
- ( grep -v -- "^${SLICE_ID} BLOCK " $DBFILE; \
- echo "${SLICE_ID} BLOCK ${block_n}" ) > ${DBFILE}.tmp
- mv ${DBFILE}.tmp ${DBFILE}
- else
- debug "Block $block_n found for user $SLICE_ID"
- fi
-
- RULE_IN_MAX=$(($RULE_BASE + $(($M * $block_n))))
- RULE_IN_MIN=$(($RULE_IN_MAX - $M))
- debug "Block $block_n, with rules <${RULE_IN_MIN}:${RULE_IN_MAX}>"
- debug "Corresponding to ipfw rules <$(($RULE_IN_MIN + 39999)):$(($RULE_IN_MAX + 39999))>"
- debug "where the last rule number belongs to the next slice."
+ debug "Search for slice_id: ${slice_id} type: ${type} port: ${arg}"
- new_pipe=1
- set `allocate_resources $RULE_IN_MIN $RULE_IN_MAX`
- rule_base=$1; pipe_base=$2
+ set `find_allocate ${slice_id} ${type} ${arg}`
+ local ipfw_rule=$1 pipe_index=$2 new_rule=$3
- [ $rule_base = 0 ] && abort "no resources available"
- debug "found free resources rule: $rule_base pipe: $pipe_base"
+ [ ${ipfw_rule} = 0 ] && abort "No resources available"
+ debug "Found or allocated resources ipfw_rule: ${ipfw_rule} and pipe_index: ${pipe_index}"
- add_rule $new_pipe $type $arg $rule_base $pipe_base $timeout
+ 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
}
#
#
# 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
}
# 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
}
# For each of these slices we reserve a block of M ipfw rules
# starting at some RULE_BASE rule number.
# The database entry for this info has the form
-# XID BLOCK block_number
+# XID BLOCK block_index
# where blocks are numbered sequentially from 1.
-# The actual rule number is RULE_BASE + M*(block_number)
-# (we don't care if we waste some rules)
+# The actual ipfw rule numbers for the block are the M rules starting at:
+# IPFW_RULE_MIN + (M-1)*(block_number)
#
# - one entry for each predefined config (CLIENT, SERVER, SERVICE).
# The database entry for this info has the form
-# XID {CLIENT|SERVER|SERVICE} arg rule_nr pipe_index
-# rule_nr is the absolute rule number for this configuration
-# (it must be within the block of M rules allocated to the slice)
+# XID {CLIENT|SERVER|SERVICE} arg ipfw_rule pipe_index
+# ipfw_rule is the unique ipfw rule number used for this configuration
+# (it must be within the block of M rule indexes allocated to the slice)
# pipe_index is the index of the couple of pipes used for the
-# configuration. pipe_index starts from 1.
+# configuration. pipe_index starts from 1. The actual pipes are
+# ipfw_pipein = IPFW_PIPE_MIN + 2*(pipe_index-1)
+# ipfw_pipeout = ipfw_pipein + 1
#
#-- main starts here
debug "--- $0 START for $SLICENAME ---"
-# If the db does not exist, create it and we clean rules and pipes
+# 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