#!/bin/sh # # Marta Carbone # Copyright (C) 2009 UniPi # $Id$ # # This script is the backend to be used with # the vsys system. # It allows to configure dummynet pipes and queues. # In detail it: # - read the user's input from the input pipe # - validate the input # - set the firewall # - put results on the output vsys pipe # # This script expect to read from the input vsys # pipe a line formatted as follow: # ${PORT} ${TIMEOUT} # the timeout value is expressed as: # week, day, month or anything else accepted by the date command # save the slicename SLICE=$1 LOG_FILE=/tmp/netconfig.log # programs CUT=/usr/bin/cut SED=/bin/sed IPFW=/sbin/ipfw # set to 0 to disable debug messages DEBUG=0 debug() { # $1 message to be displayed [ x"${DEBUG}" != x"0" ] && echo $1 >>{LOG_FILE}; } abort() { # $1 message to be displayed echo "$1" exit 1 } user_error() { # $1 message to be displayed echo "1 User error: $1" exit 1 } filter() { # $* variables to be filtered # allowed chars are: numbers, upcase and lowecase # chars, and the following symbols: . _ - / echo "$*" | ${SED} -r 's/[^0-9a-zA-Z. _\/\-]*//g' } # Add ipfw pipe and rules # We use the PORT number to configure the # pipe, and add rules for that port. # The default directory is the slicename root add_rules() { # $1 timeout value $2 delete local EXPIRE debug "Add a new rule, check for deletion flag"; if [ ${2} -eq 1 ]; then #echo "Rules and pipes deleted"; return; fi debug "Add a new rule" # schedule the rule deletion EXPIRE=`date --date="${TIMEOUT}" +%s` [ x"${EXPIRE}" = x"" ] && abort "Date format $1 not valid" # move in the slice root dir cd /vservers/${SLICE}/root #echo ${CONFIG_STRING} | ${SED} -e "s/ profile \(.[^ ]\)/ profile \/vservers\/${SLICE}\/\1/g" # check syntax, if ok execute # add rules local IPFW_CHECK="${IPFW} -n " local ERROR=0 [ $ERROR -eq 0 ] && \ ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from ${ME} to any src-port ${PORT} // ${EXPIRE} ${SLICE} let "ERROR += $?" [ $ERROR -eq 0 ] && \ ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from any to ${ME} dst-port ${PORT} let "ERROR += $?" [ $ERROR -eq 0 ] && \ ${IPFW_CHECK} pipe ${PIPE_N} config ${CONFIG_STRING} if [ ! $ERROR -eq 0 ]; then echo "Some errors occurred not executing" user_error "ipfw syntax error" fi # add rules ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from ${ME} to any src-port ${PORT} // ${EXPIRE} ${SLICE} ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from any to ${ME} dst-port ${PORT} # config pipe ${IPFW} pipe ${PIPE_N} config ${CONFIG_STRING} } # Delete a given link delete_link() { ipfw delete ${RULE_N} ipfw pipe delete ${RULE_N} } # The rule we want to configure already exist. # Check for slice owner matching. modify_rule() { local RULE RULE=`ipfw list ${PORT} 2>&1 | cut -d ' ' -f 12`; if [ "${RULE}" = "${SLICE}" ] ; then # replace the link configuration debug "The rule already exist, the owner match, delete old rule" echo "Owner match" delete_link add_rules ${TIMEOUT} ${DELETE} else user_error "the rule already exist, ant you are not the slice owner, try later" fi } # process a single line of input # this line has the following format: # ipfw # pipe # port timeout configuration_string process() { local TMP; # temporary var debug "Received from the input pipe: $1" # allow netconfig ipfw show # allow netconfig pipe show CMD=`echo $1 | cut -d\ -f 1` if [ x${CMD} == x"ipfw" ]; then ipfw show return 0 else if [ x${CMD} == x"pipe" ]; then ipfw pipe show return 0 fi fi ARGS=`echo $1 | wc -w` if [ $ARGS -le 2 ]; then abort "One or more input parameter is missing" fi # filter input TMP=`echo $1 | cut -d\ -f 1` PORT=`filter $TMP` TMP=`echo $1 | cut -d\ -f 2` TIMEOUT=`filter $TMP` TMP=`echo $1 | cut -d\ -f 3` DELETE=`filter $TMP` TMP=`echo $1 | cut -d\ -f 4-` CONFIG_STRING=`filter $TMP` debug "PORT: $PORT" debug "DELETE: $DELETE" debug "TIMEOUT: $TIMEOUT" debug "configuration string: $CONFIG_STRING" # find the ip address ME=`/sbin/ip -o addr show | grep -v "1:\ lo" | grep "inet " | cut -d " " -f7 | cut -d "/" -f1 | head -n1` # deny port <= 1024 [ ${PORT} -le 1024 ] && user_error "it is not allowed to modify the port range [0-1024]" # start to configure pipes and rules PIPE_N=${PORT} RULE_N=${PORT} # check if the link is already configured ipfw list ${PORT} 2>&1 if [ x"$?" != x"0" ]; then # new rule, add and set owner/timeout add_rules ${TIMEOUT} ${DELETE} else # the rule already exist, check owner modify_rule fi } # main starts here debug "Debug activated" requests=[] i=0 while read request do # read -a read arguments in array # XXX skip lines starting with # requests[$i]=$request; let i=$i+1 done # create the lock # process requests for i in `/usr/bin/seq 0 $((${#requests[*]} - 1))` do process "${requests[$i]}" done # delete the lock exit 0