From 868569ce538fca4c05e503fcaf684a723b783325 Mon Sep 17 00:00:00 2001
From: Marta Carbone <marta@prova.iet.unipi.it>
Date: Thu, 11 Jun 2009 09:12:42 +0000
Subject: [PATCH] Added ipfw backend script.

---
 exec/ipfw-be      | 189 ++++++++++++++++++++++++++++++++++++++++++++++
 vsys-scripts.spec |   5 +-
 2 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100755 exec/ipfw-be

diff --git a/exec/ipfw-be b/exec/ipfw-be
new file mode 100755
index 0000000..7e22a7c
--- /dev/null
+++ b/exec/ipfw-be
@@ -0,0 +1,189 @@
+#!/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} <dummynet parameters>
+# 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
+        local EXPIRE
+
+	debug "Add a new rule"
+        # schedule the rule deletion
+        EXPIRE=`date --date="${TIMEOUT}" +%s`
+        [ x"${EXPIRE}" = x"" ] && abort "Date format $1 not valid"
+
+	# prepend the profile name with the vserver directory
+	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 ${PARSED_CONFIGURATION}
+
+        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 ${PARSED_CONFIGURATION}
+}
+
+# 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}
+        else
+                user_error "the rule already exist, ant you are not the slice owner, try later"
+        fi
+}
+
+# process a single line of input, a request
+process()
+{
+	local TMP;		# temporary var
+
+	debug "Received from the input pipe: $1"
+
+	ARGS=`echo $1 | wc -w`
+	if [ $ARGS -le 3 ]; 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-`
+	CONFIG_STRING=`filter $TMP`
+
+	debug "PORT: $PORT"
+	debug "TIMEOUT: $TIMEOUT"
+	debug "configuration string: $CONFIG_STRING"
+
+	# 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}
+
+	return 0
+	# 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
+	else				# the rule already exist, check owner
+		modify_rule
+	fi
+
+}
+
+# main starts here
+
+	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]}"
+		add_rules
+	done
+
+	# delete the lock
+	exit 0
diff --git a/vsys-scripts.spec b/vsys-scripts.spec
index f67a198..40338ad 100644
--- a/vsys-scripts.spec
+++ b/vsys-scripts.spec
@@ -8,7 +8,7 @@
 
 %define name vsys-scripts
 %define version 0.95
-%define taglevel 3
+%define taglevel 4
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 
@@ -54,6 +54,9 @@ rm -rf $RPM_BUILD_ROOT
 %postun
 
 %changelog
+* Thu Jun 11 2009 Marta Carbone <marta.carbone@iet.unipi.it> - 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 ~/
 
-- 
2.47.0