Added `ipfw show' and `ipfw pipe show' commands. Minor fix.
[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
60         local EXPIRE
61
62         debug "Add a new rule"
63         # schedule the rule deletion
64         EXPIRE=`date --date="${TIMEOUT}" +%s`
65         [ x"${EXPIRE}" = x"" ] && abort "Date format $1 not valid"
66
67         # move in the slice root dir
68         cd /vservers/${SLICE}/root
69         #echo ${CONFIG_STRING} | ${SED} -e "s/ profile \(.[^ ]\)/ profile \/vservers\/${SLICE}\/\1/g"
70
71         # check syntax, if ok execute
72         # add rules
73         local IPFW_CHECK="${IPFW} -n "
74         local ERROR=0
75
76         [ $ERROR -eq 0 ] && \
77                 ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from me to any src-port ${PORT} // ${EXPIRE} ${SLICE}
78         let "ERROR += $?"
79         [ $ERROR -eq 0 ] && \
80                 ${IPFW_CHECK} add ${RULE_N} pipe ${PIPE_N} ip from any to me dst-port ${PORT}
81
82         let "ERROR += $?"
83         [ $ERROR -eq 0 ] && \
84                 ${IPFW_CHECK} pipe ${PIPE_N} config ${PARSED_CONFIGURATION}
85
86         if [ ! $ERROR -eq 0 ]; then
87                 echo "Some errors occurred not executing"
88                 user_error "ipfw syntax error"
89         fi
90
91         # add rules
92         ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from me to any src-port ${PORT} // ${EXPIRE} ${SLICE}
93         ${IPFW} add ${RULE_N} pipe ${PIPE_N} ip from any to me dst-port ${PORT}
94
95         # config pipe
96         ${IPFW} pipe ${PIPE_N} config ${PARSED_CONFIGURATION}
97 }
98
99 # Delete a given link
100 delete_link()
101 {
102         ipfw delete ${RULE_N}
103         ipfw pipe delete ${RULE_N}
104 }
105
106 # The rule we want to configure already exist.
107 # Check for slice owner matching.
108 modify_rule()
109 {
110         local RULE
111
112         RULE=`ipfw list ${PORT} 2>&1 | cut -d ' ' -f 12`;
113         if [ "${RULE}" = "${SLICE}" ] ; then    # replace the link configuration
114                 debug "The rule already exist, the owner match, delete old rule"
115                 echo "Owner match"
116                 delete_link
117                 add_rules ${TIMEOUT}
118         else
119                 user_error "the rule already exist, ant you are not the slice owner, try later"
120         fi
121 }
122
123 # process a single line of input, a request
124 process()
125 {
126         local TMP;              # temporary var
127
128         debug "Received from the input pipe: $1"
129
130         # allow netconfig ipfw show
131         # allow netconfig pipe show
132
133         CMD=`echo $1 | cut -d\  -f 1`
134         if [ x${CMD} == x"ipfw" ]; then
135                 ipfw show
136                 return 0
137         else if [ x${CMD} == x"pipe" ]; then
138                 ipfw pipe show
139                 return 0
140         fi
141         fi
142
143         ARGS=`echo $1 | wc -w`
144         if [ $ARGS -le 3 ]; then
145                 abort "One or more input parameter is missing"
146         fi
147
148         # filter input
149         TMP=`echo $1 | cut -d\  -f 1`
150         PORT=`filter $TMP`
151         TMP=`echo $1 | cut -d\  -f 2`
152         TIMEOUT=`filter $TMP`
153         TMP=`echo $1 | cut -d\  -f 3-`
154         CONFIG_STRING=`filter $TMP`
155
156         debug "PORT: $PORT"
157         debug "TIMEOUT: $TIMEOUT"
158         debug "configuration string: $CONFIG_STRING"
159
160         # deny port <= 1024
161         [ ${PORT} -le 1024 ] && user_error "it is not allowed to modify the port range [0-1024]"
162
163         # start to configure pipes and rules
164         PIPE_N=${PORT}
165         RULE_N=${PORT}
166
167         # check if the link is already configured
168         ipfw list ${PORT} 2>&1
169
170         if [ x"$?" != x"0" ]; then      # new rule, add and set owner/timeout
171                 add_rules
172         else                            # the rule already exist, check owner
173                 modify_rule
174         fi
175
176 }
177
178 # main starts here
179
180         requests=[]
181         i=0
182
183         while read request
184         do
185                 # read -a read arguments in array
186                 # XXX skip lines starting with #
187                 requests[$i]=$request;
188                 let i=$i+1
189         done
190
191         # create the lock
192
193         # process requests
194         for i in `/usr/bin/seq 0 $((${#requests[*]} - 1))`
195         do
196                 process "${requests[$i]}"
197         done
198
199         # delete the lock
200         exit 0