3 # Marta Carbone, Luigi Rizzo
4 # Copyright (C) 2009 Universita` di Pisa
7 # This script the vsys backend used to configure emulation.
9 # - reads the user's input from the vsys input pipe
10 # - validates the input
11 # - configures the firewall
12 # - writes results on the output vsys pipe
14 # Configurable variables are at the beginning
16 # If HOOK is set the program is called before configuring a rule.
17 # A sample hook can be found in the ipfwroot.rpm package,
18 # it can be used to collect statistical information on dummynet usage.
19 # To configure an hook, set the HOOK variable as follow:
20 # HOOK=/tmp/sample_hook
22 # You should not touch anything below.
24 # We assume three type of connections
25 # SERVER we know the local port P, and do the
26 # bind/listen/accept on the local socket.
27 # pipe_in in dst-port P
28 # pipe_out out src-port P
30 # CLIENT we know the remote port P, and do a connect to it
31 # (src and dst are swapped wrt the previous case)
32 # pipe_in in src-port P
33 # pipe_out out dst-port P
35 # SERVICE we run a server on local port P, and also connect
36 # from local clients to remote servers on port P.
37 # pipe_in in { dst-port P or src-port P }
38 # pipe_out out { src-port P or dst-port P }
40 # On a given port a user can have one CLIENT and/or one SERVER
41 # configuration or one SERVICE configuration.
42 # When a SERVICE configuration is installed any existing CLIENT
43 # and SERVER configuration on the same port are removed.
44 # When a CLIENT or SERVER configuration is installed any existing
45 # SERVICE configuration on the same port is removed.
47 # The following is a case that is implemented as SERVER
48 # D we run a server on local port P, and also connect
49 # to remote servers but doing a bind(P) before connect().
50 # In terms of rules, this is not distinguishable from
51 # the SERVER case, however it would be different if we
52 # had a way to tell SERVER from CLIENT sockets
53 # pipe_in in dst-port P
54 # pipe_out out src-port P
56 # The database of current ipfw and dummynet configuration is in a
57 # file which is regenerated on errors. The format is
59 # slice_id type arg rule_base pipe_base timeout
61 # (lines starting with '#' are comments and are ignored)
62 # For each configuration we allocate one rule number in ipfw,
63 # and two sequential pipe numbers.
65 # globals, do not touch below
66 VERBOSE=0 # set to !0 to enable debug messages
67 TEST=0 # set to 1 for test mode
70 lockfile=/var/lock/ipfw.lock
72 # These values are the keys used in the database for blocks,
74 # The index rule numbers allocated to a slice can be computed
75 # with the following formula:
76 # index_min_rule = $(($RULE_BASE + $(($M*$block_n))))
77 # where block_n is the block number associated with the slice
78 # and M is the block size.
82 RULE_BASE=10001 # the hightest rule is RULE_BASE + (M*BLOCK_MAX)
85 # These are the actual rule numbers used in ipfw
90 # The mapping between keys and ipfw configuration number follow:
91 # rule_nr 10001..20000 are mapped to ipfw_rules 50000..59999 (n+39999)
92 # pipe_nr 1..25000 are mapped to ipfw_pipes 10000-59999 (n*2+9998)
93 # Rule index can be mapped to ipfw rules with the following formula:
94 # ipfw_rule = $(($index_rule + 39999))
95 # Pipes index can be mapped to ipfw pipes with:
96 # ipfw_pipein = $(($index_pipe + $index_pipe + 9998))
97 # ipfw_pipeout = $(($ipfw_pipein + $1))
99 # the skipto and the generic default rule
100 # these values are used to initialize the firewall
101 SLICE_TABLE=1 # table number used for slice ids lookup
102 S=1000 # firewall rule number for the skipto rule
103 D=2000 # default rule for reserved section
105 # set slicename and slice_id
106 # these are the credential of the user invoking the backend
108 if [ $SLICENAME = 0 ]; then
111 SLICE_ID=`id -u $SLICENAME`
115 # XXX check consistency for variables {}
118 [ -x ${SED} ] || { SED=`which sed` ; SEDOPT=-E ; }
120 IPFW_CHECK="/sbin/ipfw -n"
122 debug() { # $1 message to be displayed
123 [ x"${VERBOSE}" != x"0" ] && echo "ipfw-be: $1"
126 # if the first argument is -v, enable verbose mode
128 [ x"$1" = x"-v" -o x"$2" = x"-v" ] && VERBOSE=1
132 [ x"$1" = x"-q" -o x"$2" = x"-q" ] || return
134 IPFW="/bin/echo ipfw:"
135 IPFW_CHECK="/bin/echo ipfw -n:"
138 abort() { # $1 message to be displayed in case of error
140 echo "ipfw-be aborting (netconfig help): $1"
144 # remove dangerous characters from user input
145 # if present, the leading '-v/-t' will be removed
146 filter() { # $* variables to be filtered
147 [ x${1} = x"-v" -o x${1} = x"-q" ] && shift
148 [ x${1} = x"-v" -o x${1} = x"-q" ] && shift
149 # allowed chars are: numbers, uppercase and lowercase letters,
150 # spaces, and the following symbols: .,_-/
151 echo "$*" | ${SED} ${SEDOPT} 's/[^\t0-9a-zA-Z., _\/\{}-]*//g'
154 # remove all entries from the ipfw config, and create an empty db
158 # we would like to delete ranges of rules and pipes but this
159 # is not supported so for the time being we kill them all
161 ${IPFW} -q pipe flush
162 # ${IPFW} delete ${IPFW_RULE_MIN}-${IPFW_RULE_MAX}
163 # ${IPFW} pipe delete ${IPFW_PIPE_MIN}-${IPFW_PIPE_MAX}
164 # since all rules are now deleted, we should initialize the firewall
168 # Add the ipfw rule/pipe and update the database.
169 # The pipe-in and pipe_out config are through global variables
170 # CONFIG_IN CONFIG_OUT because they may be long.
171 # Other arguments are on the command line
172 add_rule() { # new_rule type arg rule pipe_base timeout
173 local new_rule=$1 type=$2 arg=$3
174 local rule_base=$4 pipe_base=$5 timeout=$6
175 local pipe_in pipe_out rule_in rule_out check_timeout
177 # If we use a profile file, locate the user directory
178 # move in the slice root dir XXX todo
179 [ "$TEST" != "1" ] && cd /vservers/${SLICENAME}/root
180 #echo ${CONFIG_STRING} | ${SED} -e "s/ profile \(.[^ ]\)/ profile \/vservers\/${SLICENAME}\/\1/g"
182 # first, call ipfw -n to check syntax, if ok move on and do the action
183 pipe_in=$(($pipe_base + $pipe_base + 9998))
184 pipe_out=$(($pipe_in + 1))
185 local del # anything to delete ?
186 local rule_nr=$(($rule_base + 39999)) # formula for individual rules
187 if [ x"$new_rule" != x"0" ] ; then
190 rule_in="dst-port $arg"
191 rule_out="src-port $arg"
195 rule_in="src-port $arg"
196 rule_out="dst-port $arg"
200 rule_in="{ src-port $arg or dst-port $arg }"
201 rule_out="{ src-port $arg or dst-port $arg }"
205 abort "invalid service type $type"
209 rule_in="pipe ${pipe_in} in jail $SLICE_ID ${rule_in} // $type $arg"
210 rule_out="pipe ${pipe_out} out jail $SLICE_ID ${rule_out} // $type $arg"
211 ${IPFW_CHECK} add ${rule_nr} $rule_in > /dev/null || \
212 abort "ipfw syntax error $rule_in"
213 ${IPFW_CHECK} add ${rule_nr} $rule_out > /dev/null || \
214 abort "ipfw syntax error $rule_out"
217 # check error reporting
218 ${IPFW_CHECK} pipe ${pipe_in} config ${CONFIG_PIPE_IN} > /dev/null || \
219 abort "ipfw syntax error pipe_in"
220 ${IPFW_CHECK} pipe ${pipe_out} config ${CONFIG_PIPE_OUT} > /dev/null || \
221 abort "ipfw syntax error pipe_out"
223 # all good, delete and add rules if necessary
224 [ "$del" = "service" ] && do_delete $SLICE_ID service $arg
225 [ "$del" = "cli_ser" ] && do_delete $SLICE_ID client $arg
226 [ "$del" = "cli_ser" ] && do_delete $SLICE_ID server $arg
227 [ "$new_rule" != "0" ] && ${IPFW} add ${rule_nr} $rule_in > /dev/null
228 [ "$new_rule" != "0" ] && ${IPFW} add ${rule_nr} $rule_out > /dev/null
230 ${IPFW} pipe ${pipe_in} config ${CONFIG_PIPE_IN}
231 ${IPFW} pipe ${pipe_out} config ${CONFIG_PIPE_OUT}
233 # send output to the user
234 ${IPFW} show ${rule_nr}
235 ${IPFW} pipe ${pipe_in} show
236 ${IPFW} pipe ${pipe_out} show
238 [ "$TEST" = "1" ] && return
239 # add to the database
240 ( grep -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE; \
241 echo "${SLICE_ID} ${type} ${arg} ${rule_base} ${pipe_base} ${timeout}" ) > ${DBFILE}.tmp
242 mv ${DBFILE}.tmp ${DBFILE}
245 # Delete a given configuration
246 do_delete() { # type arg
247 local pipe_in pipe_out pipe_base rule_base rule_nr
250 [ "${type}" = "BLOCK" ] && abort "A Block can not be deleted"
251 [ "${arg}" = "" ] && abort "Missing args on 'delete', expected on of {SERVICE|SERVER|CLIENT} port_number"
252 set `find_rule $SLICE_ID $type $arg`
253 rule_base=$1; pipe_base=$2
254 [ "$rule_base" = "0" ] && return # no rules found
256 rule_nr=$(($rule_base + 39999)) # XXX only individual rules
257 pipe_in=$(($pipe_base + $pipe_base + 9998))
258 pipe_out=$(($pipe_in + 1))
260 $IPFW delete ${rule_nr}
261 $IPFW pipe delete ${pipe_in}
262 $IPFW pipe delete ${pipe_out}
263 echo "removed configuration ${SLICE_ID} ${type} ${arg}"
264 [ "$TEST" = "1" ] && return
265 # remove from the database
266 grep -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE > ${DBFILE}.tmp
267 mv ${DBFILE}.tmp ${DBFILE}
269 # XXX if the use block is empty
270 # remove the table entry from ipfw and from the db
271 # not yet implemented
274 # compare the argument with the first two field of
276 # On match returns the block number, otherwise returns 0.
277 find_block() { # $1 slice_id
279 ret=`grep -- "^$1 BLOCK " $DBFILE`
281 [ x"$ret" = x ] && echo "0" && return # nothing found
282 # ignore multiple matches. If the db is corrupt we are
288 # called with the database file as input
289 # compare the tuple <slice_id type arg> with
290 # the current firewall configuration. The database contains
291 # slice_id type arg rule_base pipe_base timeout
292 # On match returns <rule_base pipe_base timeout>
293 # On non match returns 0 0 0
294 find_rule() { # $1 slice_id $2 type $3 arg
296 ret=`grep -- "^$1 $2 $3 " $DBFILE`
298 [ x"$ret" = x ] && echo "0 0 0 " && return # nothing found
299 # ignore multiple matches. If the db is corrupt we are
306 # Find a hole in a list of numbers within a range (boundaries included)
307 # The input is passed as a sorted list of numbers on stdin.
308 # Return a "0" rule if there is no rule free
309 find_hole() { # min max
310 local min=$1 cand=$1 max=$2 line
312 [ $line -lt $min ] && continue
313 [ $line -ne $cand ] && break # found
314 [ $cand -ge $max ] && cand=0 && break # no space
320 # returns a free rule and pipe base for client|server|service
322 # Returns r=0 if there are no resources available
323 allocate_resources() {
325 # remove comments, extract field, sort
326 p=`grep -v '^#' $DBFILE | grep -v BLOCK | awk '{print $5}' | sort -n | \
327 find_hole $PIPE_MIN $PIPE_MAX`
328 r=`grep -v '^#' $DBFILE | grep -v BLOCK | awk '{print $4}' | sort -n | \
330 [ $r = 0 -o $p = 0 ] && r=0 # no resources available
335 # execute functions from root context
336 # can be used from root context as follow:
337 # echo "super $command $args" | /vsys/ipfw-be 0
338 do_super() { # $arguments...
347 abort "Invalid super command"
353 # show ipfw rules and pipes filtering on slice_id
354 # If the first argument is 0 filter rules,
355 # otherwise filter pipes
356 do_show() { #$1 show rules or pipes
359 if [ $1 == "0" ]; then
360 list=`grep "^$SLICE_ID " $DBFILE | grep -v BLOCK | cut -d " " -f 4`
361 for i in $list; do ipfw_list="$ipfw_list $(($i + 39999))"; done
362 [ -n "${ipfw_list}" ] && ${IPFW} show $ipfw_list
364 # ipfw pipe show does not selectively filter pipes
365 # XXX so leave this code commented and show all pipes
366 #list=`grep "^$SLICE_ID " $DBFILE | grep -v BLOCK | cut -d " " -f 5`
367 # the pipe list is build adding two ipfw pipes for each pipe index
368 #for i in $list; do ipfw_list="$ipfw_list $(($i + $i + 9998)) $(($i + $i + 9998 +1)) "; done
369 #[ -n "${ipfw_list}" ] && ${IPFW} pipe show $ipfw_list
375 # refresh the rule timeout
376 do_refresh() { # type arg timeout
377 local pipe_in pipe_out pipe_base rule_base rule_nr
378 local type=$1 arg=$2 timeout=$3
380 debug "do_refresh type: <$type> arg: <$arg> timeout: <$timeout>"
381 [ "${type}" = "BLOCK" ] && abort "BLOCK rule not valid"
382 [ "${timeout}" = "" ] && abort "Missing args on 'refresh', expected on of {SERVICE|SERVER|CLIENT} port_number"
383 set `find_rule $SLICE_ID $type $arg`
384 rule_base=$1; pipe_base=$2
385 [ "${rule_base}" = "0" ] && debug "no rules found" && return 0 # no rules found
387 rule_nr=$(($rule_base + 39999)) # XXX only individual rules
388 pipe_in=$(($pipe_base + $pipe_base + 9998))
389 pipe_out=$(($pipe_in + 1))
390 debug "ipfw rule and pipes value: rule: <$rule_nr> pipe in: <$pipe_in> pipe_out: <$pipe_out>"
392 [ "$TEST" = "1" ] && return
393 # update the database with the new timeout value
394 ( grep -v -- "^${SLICE_ID} ${type} ${arg} " $DBFILE; \
395 echo "${SLICE_ID} ${type} ${arg} ${rule_base} ${pipe_base} ${timeout}" ) > ${DBFILE}.tmp
396 mv ${DBFILE}.tmp ${DBFILE}
397 echo "refreshed timeout for rule ${type} ${arg}"
401 # A request is made by a set of arguments formatted as follow:
403 # config {server|client|service} arg [-t timeout] PIPE_IN <pipe_conf> PIPE_OUT <pipe_conf>
404 # show {rules|pipes} [args]
407 # The timeout value is expressed as:
408 # week, day, month or anything else accepted by the date command.
409 # The id of the slice issuing the request is in the $SLICE_ID variable,
410 # set at the beginning of this script.
413 local timeout TMP i rule_base pipe_base
414 local slicename=${SLICENAME}
416 local debug_args="$*";
417 local type=$1 ; shift
419 debug "Received command: <$cmd> arguments: <$debug_args>"
421 # set the timeout value
422 # if present, extract the '-t timeout' substring from the command line
423 timeout=`echo ${args} | ${SED} ${SEDOPT} 's/(.+)( -t [a-zA-Z0-9]+ )(.*)/\2/'`
424 # if the '-t timeout' is specified, use the user define timeout value
425 if [ "${timeout}" != "${args}" ] ; then # match
426 # remove the '-t ' option
427 timeout=`echo ${timeout} | ${SED} ${SEDOPT} 's/-t //'`
428 check_timeout ${timeout} # abort on error
429 # clean the arguments
430 args=`echo ${args} | ${SED} ${SEDOPT} 's/(.+)( -t [a-zA-Z0-9]+ )(.*)/\1 \3/'`
432 # use the default value, no need to check for correctness, no need to clean arguments
433 timeout=`date --date="1day" +%s` # default to 1 day
436 debug "Timeout $timeout"
437 # Handle special requests: show and delete
440 [ "$type" = "server" ] && do_config $timeout $type $args && return 0
441 [ "$type" = "client" ] && do_config $timeout $type $args && return 0
442 [ "$type" = "service" ] && do_config $timeout $type $args && return 0
443 abort "'config' should be followed by {server|client|service}"
446 do_delete ${SLICE_ID} $type $args
449 do_refresh $type $args $timeout && return 0
452 [ "$type" = "rules" ] && do_show 0 && return 0
453 [ "$type" = "pipes" ] && do_show 1 && return 0
454 abort "'show' should be followed by {rules|pipes}"
457 [ $SLICE_ID = 0 ] && do_super $type $args && return 0
458 abort "no permission for ipfw-be super execution"
464 # help XXX to be done
465 abort "'command' should be one of {show|config|delete|refresh|release}"
470 # validate the timeout
471 check_timeout() { # timeout
472 local tt=`date --date="${1}" +%s`
473 [ "$?" != "0" ] && abort "Date format $1 not valid"
476 do_config() { # timeout type arg PIPE_IN pipe_conf PIPE_OUT pipe_conf
477 local timeout=$1; shift
479 local arg=$1; shift # XXX addr not yet implemented
481 [ "$1" != "PIPE_IN" ] && abort "Missing addr:port, or PIPE_IN requested"
484 # read pipe in configuration
486 while [ "$1" != "" -a "$1" != "PIPE_OUT" ] ; do
490 CONFIG_PIPE_IN="$i" # XXX local ?
491 [ "$CONFIG_PIPE_IN" = "" ] && abort "Missing pipe in configuration"
493 [ "$1" != "PIPE_OUT" ] && abort "Missing pipe in configuration, or missing PIPE_OUT"
496 # read pipe out configuration
498 while [ "$1" != "" ] ; do
502 CONFIG_PIPE_OUT="$i" # XXX local ?
503 [ "$CONFIG_PIPE_OUT" = "" ] && abort "Missing pipe out configuration"
505 debug "Configuration Required:"
506 debug "slice_id: $SLICE_ID"
509 debug "timeout: $timeout"
510 debug "PIPE_IN: $CONFIG_PIPE_IN"
511 debug "PIPE_OUT: $CONFIG_PIPE_OUT"
512 debug "-----------------------"
514 # check if the link is already configured
515 debug "Search for ${SLICE_ID} ${type} ${arg}"
517 set `find_rule ${SLICE_ID} ${type} ${arg}`
522 if [ ! ${rule_base} = "0" ] ; then
523 debug "Rule found, just changing the pipe configuration"
524 add_rule $new_pipe $type $arg $rule_base $pipe_base $timeout
525 hook_call $type $port $rule_base $pipe_base $timeout
526 return 0; # link configured, exit
529 debug "link not found, search for a block already allocated to the user"
531 # Search if there is a block already allocated to the slice_id
532 set `find_block ${SLICE_ID}`
534 if [ ${block_n} = "0" ] ; then
535 debug "Block not found, allocate a new block"
536 # blocks are allocated in sequence, get the first free
537 block_n=`grep BLOCK $DBFILE | tail -1 | cut -d " " -f 3`
538 if [ -z $block_n ]; then
539 block_n=$(($BLOCK_MIN - 1))
541 RULE_IN_MIN=$(($RULE_BASE + $(($M*$block_n))))
542 block_n=$(($block_n +1))
543 debug "Allocated new block $block_nr to user $SLICE_ID"
544 [ $block_n -gt $BLOCK_MAX ] && abort "no block resources available"
546 # add the rule into the firewall table.
547 # note that the rule number into the table are not database number,
548 # so we need to compute the firewall number before the table insertion
549 local ipfw_rule_nr=$(($RULE_IN_MIN + 39999)) # XXX formula for individual rules
550 debug "Configuring table: <${IPFW_CHECK} table $SLICE_TABLE add ${SLICE_ID} ${ipfw_rule_nr}>"
551 ${IPFW_CHECK} table $SLICE_TABLE add ${SLICE_ID} ${rule_nr} > /dev/null || \
552 abort "ipfw syntax error $rule_out"
553 ${IPFW} table $SLICE_TABLE add ${SLICE_ID} ${ipfw_rule_nr} > /dev/null
555 [ "$TEST" = "1" ] && return
556 # add the block declaration to the database
557 ( grep -v -- "^${SLICE_ID} BLOCK " $DBFILE; \
558 echo "${SLICE_ID} BLOCK ${block_n}" ) > ${DBFILE}.tmp
559 mv ${DBFILE}.tmp ${DBFILE}
561 debug "Block $block_n found for user $SLICE_ID"
564 RULE_IN_MAX=$(($RULE_BASE + $(($M * $block_n))))
565 RULE_IN_MIN=$(($RULE_IN_MAX - $M))
566 debug "Block $block_n, with rules <${RULE_IN_MIN}:${RULE_IN_MAX}>"
567 debug "Corresponding to ipfw rules <$(($RULE_IN_MIN + 39999)):$(($RULE_IN_MAX + 39999))>"
568 debug "where the last rule number belongs to the next slice."
571 set `allocate_resources $RULE_IN_MIN $RULE_IN_MAX`
572 rule_base=$1; pipe_base=$2
574 [ $rule_base = 0 ] && abort "no resources available"
575 debug "found free resources rule: $rule_base pipe: $pipe_base"
577 add_rule $new_pipe $type $arg $rule_base $pipe_base $timeout
578 hook_call $type $port $rule_base $pipe_base $timeout
582 # acquire the lock XXX check lockfile
584 [ "$TEST" = 1 ] && return
585 lockfile -s 0 -r 0 $lockfile 2> /dev/null
586 if [ $? -ne 0 ] ; then
587 echo "lock acquisition failed"
599 # initialize the firewall with PlanetLab default rules
601 ${IPFW} add $S skipto tablearg lookup jail $SLICE_TABLE
602 ${IPFW} add $D allow all from any to any
606 # if present, call a hook function
608 # slice_id type port rule_base pipe_base timeout
610 if [ -n "${HOOK}" -a -x "${HOOK}" ]; then
611 ${HOOK} ${SLICE_ID} "$*" &
618 ./neconfig [SERVER|CLIENT|SERVICE] port [-t timeout] \
619 PIPE_IN <pipe in configuration> PIPE_OUT <pipe out configuration>
620 ./netconfig show [rules|pipes]
621 ./netconfig delete [SERVER|CLIENT|SERVICE] port
622 ./netconfig refresh [-t timeout] [SERVER|CLIENT|SERVICE] port
624 We assume three type of connections
625 SERVER we know the local port P, and do the
626 bind/listen/accept on the local socket.
627 pipe_in in dst-port P
628 pipe_out out src-port P
630 CLIENT we know the remote port P, and do a connect to it
631 (src and dst are swapped wrt the previous case)
632 pipe_in in src-port P
633 pipe_out out dst-port P
635 SERVICE we run a server on local port P, and also connect
636 from local clients to remote servers on port P.
637 pipe_in in { dst-port P or src-port P }
638 pipe_out out { src-port P or dst-port P }
640 On a given port a user can have one CLIENT and/or one SERVER
641 configuration or one SERVICE configuration.
642 When a SERVICE configuration is installed any existing CLIENT
643 and SERVER configuration on the same port are removed.
644 When a CLIENT or SERVER configuration is installed any existing
645 SERVICE configuration on the same port is removed.
647 The pipe configuration, both for the upstream and downstream link,
648 follow the dummynet syntax. A quick and not exaustive example
649 of the parameters that can be used to configure the delay,
650 the bandwidth and the packet loss rate for a link follow:
652 PIPE_IN|PIPE_OUT delay 100ms bw 1Mbit/s plr 0.1
654 The full documentation is on the manpage[1].
656 The timeout value follow the linux 'date' command format[2]
657 and can be specified as follow:
663 [1] http://www.freebsd.org/cgi/man.cgi?query=ipfw
664 [2] http://linuxmanpages.com/man1/date.1.php
668 # ALLOCATION OF RULES AND PIPES
669 # The ruleset is composed by different sections, as follow:
670 # - a first set of rules is reserved and is configurable by
671 # the root context only;
672 # - the skipto rule (S), used to optimize the slice rule search;
673 # - a second block of reserved rules;
674 # - a default (D) rule for the generic configuration;
675 # - the slice reserved rules, a block of M rules for each slice;
676 # - the firewall default rule.
679 # 1...S-1 first block of reserved rules
680 # S skipto tablearg lookup jail 1
681 # S+1..D-1 ... second block of reserved rules
682 # D allow ip from any to any
684 # RULE_BASE <block of M entries for first user>
685 # RULE_BASE+M <block of M entry for second user ...>
688 # Out of 64k rules, we allocate a block of M=50 consecutive
689 # rules to each slice using emulation. Within this block,
690 # each configuration uses one rule number and two pipes.
692 # Pipes are allocated starting from PIPE_BASE, a couple
693 # of pipes for each configuration.
696 # The database is stored on a file, and contains
697 # one line per record with this general structure
698 # XID TYPE arg1 arg2 ...
699 # whitespace separates the fields. arg1, arg2, ...
700 # have different meaning depending on the type.
702 # In the database we have the following records:
703 # - one entry for each slice that has active emulation entries.
704 # For each of these slices we reserve a block of M ipfw rules
705 # starting at some RULE_BASE rule number.
706 # The database entry for this info has the form
707 # XID BLOCK block_number
708 # where blocks are numbered sequentially from 1.
709 # The actual rule number is RULE_BASE + M*(block_number)
710 # (we don't care if we waste some rules)
712 # - one entry for each predefined config (CLIENT, SERVER, SERVICE).
713 # The database entry for this info has the form
714 # XID {CLIENT|SERVER|SERVICE} arg rule_nr pipe_index
715 # rule_nr is the absolute rule number for this configuration
716 # (it must be within the block of M rules allocated to the slice)
717 # pipe_index is the index of the couple of pipes used for the
718 # configuration. pipe_index starts from 1.
722 debug "--- $0 START for $SLICENAME ---"
724 # If the db does not exist, create it and we clean rules and pipes
725 [ ! -e ${DBFILE} ] && clean_db
727 # A request to the vsys backend is composed by a single line of input
728 read REQ # read one line, ignore the rest
729 set_verbose ${REQ} # use inital -v if present
730 set_test ${REQ} # use inital -t if present
731 REQ="`filter ${REQ}`" # remove -v and -t and invalid chars
732 debug "--- processing <${REQ}>"
733 acquire_lock # critical section
736 debug "--- $0 END ---"