Fix slicename and timeout values, use the numeric ip address instead of the 'me'...
[vsys-scripts.git] / exec / ipfw-be
1 #!/bin/sh
2 #
3 # Marta Carbone
4 # Copyright (C) 2009 UniPi
5 # $Id$
6 #
7 # This script is the backend to be used with
8 # the vsys system.
9 # It allows to configure dummynet pipes and queues.
10 # In detail it:
11 # - read the user's input from the input pipe
12 # - validate the input
13 # - set the firewall
14 # - put results on the output vsys pipe
15 #
16 # This script expect to read from the input vsys
17 # pipe a line formatted as follow:
18 # ${PORT} ${TIMEOUT} <dummynet parameters>
19 # the timeout value is expressed as:
20 # week, day, month or anything else accepted by the date command
21
22 # save the slicename
23 SLICE=$1
24
25 LOG_FILE=/tmp/netconfig.log
26
27 # programs
28 CUT=/usr/bin/cut
29 SED=/bin/sed
30 IPFW=/sbin/ipfw
31
32 # set to 0 to disable debug messages
33 DEBUG=0
34
35 debug() { # $1 message to be displayed
36         [ x"${DEBUG}" != x"0" ] && echo $1 >>{LOG_FILE};
37 }
38
39 abort() { # $1 message to be displayed
40         echo "$1"
41         exit 1
42 }
43
44 user_error() { # $1 message to be displayed
45         echo "1 User error: $1"
46         exit 1
47 }
48
49 filter() { # $* variables to be filtered
50         # allowed chars are: numbers, upcase and lowecase
51         # chars, and the following symbols: . _ - /
52         echo "$*" | ${SED} -r 's/[^0-9a-zA-Z. _\/\-]*//g'
53 }
54
55 # Add ipfw pipe and rules
56 # We use the PORT number to configure the
57 # pipe, and add rules for that port.
58 # The default directory is the slicename root
59 add_rules() { # $1 timeout value $2 delete
60         local EXPIRE
61
62         debug "Add a new rule, check for deletion flag";
63         if [ ${2} -eq 1 ]; then
64                 #echo "Rules and pipes deleted";
65                 return;
66         fi
67
68         debug "Add a new rule"
69         # schedule the rule deletion
70         EXPIRE=`date --date="${TIMEOUT}" +%s`
71         [ x"${EXPIRE}" = x"" ] && abort "Date format $1 not valid"
72
73         # move in the slice root dir
74         cd /vservers/${SLICE}/root
75         #echo ${CONFIG_STRING} | ${SED} -e "s/ profile \(.[^ ]\)/ profile \/vservers\/${SLICE}\/\1/g"
76
77         # check syntax, if ok execute
78         # add rules
79         local IPFW_CHECK="${IPFW} -n "
80         local ERROR=0
81
82         [ $ERROR -eq 0 ] && \
83                 ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from ${ME} to any src-port ${PORT} // ${EXPIRE} ${SLICE}
84         let "ERROR += $?"
85         [ $ERROR -eq 0 ] && \
86                 ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from any to ${ME} dst-port ${PORT}
87
88         let "ERROR += $?"
89         [ $ERROR -eq 0 ] && \
90                 ${IPFW_CHECK} pipe ${PIPE_N} config ${CONFIG_STRING}
91
92         if [ ! $ERROR -eq 0 ]; then
93                 echo "Some errors occurred not executing"
94                 user_error "ipfw syntax error"
95         fi
96
97         # add rules
98         ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from ${ME} to any src-port ${PORT} // ${EXPIRE} ${SLICE}
99         ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from any to ${ME} dst-port ${PORT}
100
101         # config pipe
102         ${IPFW} pipe ${PIPE_N} config ${CONFIG_STRING}
103 }
104
105 # Delete a given link
106 delete_link()
107 {
108         ipfw delete ${RULE_N}
109         ipfw pipe delete ${RULE_N}
110 }
111
112 # The rule we want to configure already exist.
113 # Check for slice owner matching.
114 modify_rule()
115 {
116         local RULE
117
118         RULE=`ipfw list ${PORT} 2>&1 | cut -d ' ' -f 12`;
119         if [ "${RULE}" = "${SLICE}" ] ; then    # replace the link configuration
120                 debug "The rule already exist, the owner match, delete old rule"
121                 echo "Owner match"
122                 delete_link
123                 add_rules ${TIMEOUT} ${DELETE}
124         else
125                 user_error "the rule already exist, ant you are not the slice owner, try later"
126         fi
127 }
128
129 # process a single line of input
130 # this line has the following format:
131 # ipfw
132 # pipe
133 # port timeout configuration_string
134 process()
135 {
136         local TMP;              # temporary var
137
138         debug "Received from the input pipe: $1"
139
140         # allow netconfig ipfw show
141         # allow netconfig pipe show
142
143         CMD=`echo $1 | cut -d\  -f 1`
144         if [ x${CMD} == x"ipfw" ]; then
145                 ipfw show
146                 return 0
147         else if [ x${CMD} == x"pipe" ]; then
148                 ipfw pipe show
149                 return 0
150         fi
151         fi
152
153         ARGS=`echo $1 | wc -w`
154         if [ $ARGS -le 2 ]; then
155                 abort "One or more input parameter is missing"
156         fi
157
158         # filter input
159         TMP=`echo $1 | cut -d\  -f 1`
160         PORT=`filter $TMP`
161         TMP=`echo $1 | cut -d\  -f 2`
162         TIMEOUT=`filter $TMP`
163         TMP=`echo $1 | cut -d\  -f 3`
164         DELETE=`filter $TMP`
165         TMP=`echo $1 | cut -d\  -f 4-`
166         CONFIG_STRING=`filter $TMP`
167
168         debug "PORT: $PORT"
169         debug "DELETE: $DELETE"
170         debug "TIMEOUT: $TIMEOUT"
171         debug "configuration string: $CONFIG_STRING"
172
173         # find the ip address
174         ME=`/sbin/ip -o addr show | grep -v "1:\ lo" | grep "inet " | cut -d " " -f7 | cut -d "/" -f1 | head -n1`
175
176         # deny port <= 1024
177         [ ${PORT} -le 1024 ] && user_error "it is not allowed to modify the port range [0-1024]"
178
179         # start to configure pipes and rules
180         PIPE_N=${PORT}
181         RULE_N=${PORT}
182
183         # check if the link is already configured
184         ipfw list ${PORT} 2>&1
185
186         if [ x"$?" != x"0" ]; then      # new rule, add and set owner/timeout
187                 add_rules ${TIMEOUT} ${DELETE}
188         else                            # the rule already exist, check owner
189                 modify_rule
190         fi
191
192 }
193
194 # main starts here
195
196         debug "Debug activated"
197         requests=[]
198         i=0
199
200         while read request
201         do
202                 # read -a read arguments in array
203                 # XXX skip lines starting with #
204                 requests[$i]=$request;
205                 let i=$i+1
206         done
207
208         # create the lock
209
210         # process requests
211         for i in `/usr/bin/seq 0 $((${#requests[*]} - 1))`
212         do
213                 process "${requests[$i]}"
214         done
215
216         # delete the lock
217         exit 0