4b89752ac234b445aebdfe65e154db2b9f508247
[planetlab-umts-tools.git] / umts_functions
1 #!/bin/bash
2
3
4 STROK="remote IP address"
5 GCOMP="comgt"
6 GCOM="/usr/bin/"${GCOMP}
7 LOGF="/tmp/umtslogs"
8 PPPD_PIDFILE="/var/run/umts_pppd.pid"
9 DESTS_FILE="/tmp/umts_dest_file"
10 FILE_TEMP_NID="/tmp/umts_temp_nid"
11 FILE_UMTS_INT="/tmp/umts_dev"
12 LOCK_DIR="/var/run/umts_lock"
13 FILE_LOCK_SLIVER="/var/run/umts_locking_sliver"
14 PPP_INT="ppp0"
15 PPPD="pppd"
16 CHAT_SCRIPTS="/etc/chatscripts"
17 UMTS_CONF="/etc/umts.conf"
18
19
20
21 function get_umts_dev(){
22         echo "/dev/umts_modem"
23 }
24
25 function init_umts(){
26         #local found=1
27         
28         if [ -e $LOCK_DIR ]; then
29                 rmdir $LOCK_DIR
30         fi
31
32         #if ! grep "umts_table" /etc/iproute2/rt_tables > /dev/null 2>&1; then
33         #       echo "20 umts_table" >> /etc/iproute2/rt_tables
34         #fi
35
36         return 0
37
38 }
39
40
41 function get_temp_nid(){
42         cat $FILE_TEMP_NID
43 }
44
45
46 #called when the connection is started
47 function conn_on(){
48         local sliver=$1
49
50         #DESTS_FILE contains added destinations
51         rm -f $DESTS_FILE 
52
53         set_temp_nid $sliver_nid
54         set_routes $sliver
55
56         cat $LOGF | grep "local"
57         return 0
58
59 }
60
61 #called when the connection is terminated
62 function conn_off(){
63         local sliver=$1
64         local ppp_addr=$2
65
66         unset_routes $sliver $ppp_addr
67
68         for i in `cat $DESTS_FILE`; do
69                 del_destination $i $sliver > /dev/null 2>&1
70         done
71
72         rm $DESTS_FILE >/dev/null 2>&1
73 }
74
75 function start_umts(){
76     local sliver=$1
77     local sliver_nid=`get_nid $sliver`
78
79     if ! grep "umts_table" /etc/iproute2/rt_tables > /dev/null 2>&1; then
80         echo "20 umts_table" >> /etc/iproute2/rt_tables
81     fi
82
83     if ! lock $sliver; then
84         return 1
85     fi  
86
87     if status_umts; then
88          echo "Already connected"
89          return 0; 
90     fi
91     
92     echo "Starting GCOM..."
93     if ! $GCOM -d `get_umts_dev`; then
94         unlock $sliver
95         return 1
96     fi
97
98     rm -f $LOGF
99
100     if [ -e $UMTS_CONF ]; then
101         . $UMTS_CONF
102     fi
103  
104     if ! [[ $APN ]]; then
105         APN="web.omnitel.it"
106     fi
107     if ! [[ $NUM ]]; then
108         NUM="*99***1#"
109     fi
110     
111
112     exec /usr/sbin/pppd nodetach `get_umts_dev` 460800 \
113                 0.0.0.0:0.0.0.0 \
114                 connect "/usr/sbin/chat -v                     \
115                 TIMEOUT         6                              \
116                 ABORT           '\nBUSY\r'                     \
117                 ABORT           '\nNO ANSWER\r'                \
118                 ABORT           '\nRINGING\r\n\r\nRINGING\r'   \
119                 ''              ATZ     OK 'ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0' OK  \
120                 'AT+CGDCONT=1,\"IP\",\"$APN\"' OK \
121                 ATD$NUM   CONNECT ''" > $LOGF &
122
123
124     #exec /usr/sbin/pppd nodetach `get_umts_dev` 460800 \
125     #           0.0.0.0:0.0.0.0 \
126     #           connect "/usr/sbin/chat -f ${CHAT_SCRIPTS}/vodaphone-it" > $LOGF &
127
128     echo $! > $PPPD_PIDFILE
129
130     sleep 5s;  #waiting for the interface to establish the link
131     if grep "$STROK" $LOGF >/dev/null 2>&1; then
132         conn_on $sliver $sliver_nid
133     else
134         #second try
135         sleep 5s;
136         if grep "$STROK" $LOGF >/dev/null 2>&1; then
137             conn_on $sliver $sliver_nid
138         else
139             stop_umts $sliver
140             return 1
141         fi
142     fi
143 }
144
145
146 function stop_umts(){
147     local sliver=$1
148     local sliver_nid=`get_nid $sliver`
149     local ppp_addr
150
151     if ! [ -e $PPPD_PIDFILE ]; then 
152         echo "Disconnected"
153         return 0;
154     fi
155
156     ppp_addr=`get_ppp_address`
157
158     if ! check_who_locked $sliver; then
159         return 1
160     fi
161
162     PID=`cat $PPPD_PIDFILE`;
163
164     if [ -d /proc/$PID ] &&  grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then        
165         kill $PID;      touch $DESTS_FILE
166
167         sleep 2s;
168     fi
169
170     if status_umts; then
171         return 1;
172     else
173         conn_off $sliver $ppp_addr
174         cat $LOGF | grep "time"
175         rm $PPPD_PIDFILE
176         unlock $sliver;
177         return 0
178     fi
179 }
180
181
182 function status_umts(){
183     local sliver=$1
184         
185     if ! [ -e $PPPD_PIDFILE ]; then return 1; fi
186     PID=`cat $PPPD_PIDFILE`
187
188     if [ -d /proc/$PID ] &&  grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then
189         return 0;
190     else 
191         return 1;
192     fi
193 }
194
195 #add the ppp interface to the slice - not used at the moment
196 function add_interface(){
197     local nid=`get_nid $1`
198     $NADDRESS --add --nid $nid --ip $PPP_INT >>$LOGFILE 2>&1;
199 }
200
201 #remove the ppp interface from the slice - not used at the moment
202 function del_interface(){
203     local nid=`get_nid $1`
204     #$NADDRESS --remove --nid $NID --ip $PPP_INT >>$LOGFILE 2>&1;
205 }
206
207 #get slice network id
208 function get_nid(){
209     id -u ${1}
210 }
211
212 function set_routes(){
213         local sliver=$1
214         local sliver_nid=`get_nid $sliver`
215         local temp_nid=`get_temp_nid`
216         local ppp_addr=`get_ppp_address`
217
218         #Asks VNET+ to tag all the packets with the respective sliver id
219         iptables -t mangle -A OUTPUT -j MARK --copy-xid 0x00
220
221         #Changes the netfilter mark of packets to trigger rerouting. 
222         #We need to change the mark because the kernel triggers the rerouting process only
223         #if it sees that the netfilter mark has been altered in the mangle iptables chain
224         iptables -t mangle -A OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid
225
226         #Adds an SNAT rule to set the source IP address of packets that are about to go out through the UMTS
227         #interface. The kernel sets the source address of packets when the first routing process happens
228         #so, without this rule, packets would have the source ip address set on the first routing process of the ethernet interface
229         iptables -t nat -A POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr
230         
231         #Restores the original netfilter mark for planetflow
232         iptables -t mangle -I POSTROUTING 1 -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid
233
234         #Forbids other slices to use the UMTS interface
235         iptables -t mangle -I POSTROUTING 2 -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP
236         
237         #Enables the explicit bind to the UMTS interface. Applications launched by the user in the slice that is using the UMTS and that
238         #bind to the UMTS interface will have packets going out through the UMTS interface 
239         ip route flush table umts_table >/dev/null 2>&1 
240         ip rule add from $ppp_addr fwmark $temp_nid table umts_table >/dev/null 2>&1
241         ip route add default dev $PPP_INT src $ppp_addr table umts_table >/dev/null 2>&1
242         ip route flush cache  >/dev/null 2>&1
243 }
244
245 function unset_routes(){
246         local sliver=$1
247         local ppp_addr=$2
248         local sliver_nid=`get_nid $sliver`
249         local temp_nid=`get_temp_nid`
250         
251
252         #removing the rules for changing the mark and the rules for SNAT 
253         iptables -t mangle -D OUTPUT -j MARK --copy-xid 0x00
254         iptables -t mangle -D OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid
255         iptables -t nat -D POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr
256         iptables -t mangle -D POSTROUTING -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid
257
258         iptables -t mangle -D POSTROUTING -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP
259
260         #disable the explicit bind to the ppp interface
261         ip rule del from $ppp_addr fwmark $temp_nid table umts_table  >/dev/null 2>&1
262         ip route del default dev $PPP_INT  src $ppp_addr table umts_table >/dev/null 2>&1
263         ip route flush cache  >/dev/null 2>&1
264
265 }
266
267 function add_destination(){
268         local dest="$1"
269         local sliver=$2
270         local sliver_nid=`get_nid $sliver`
271         local temp_nid=`get_temp_nid`
272
273         if [[ ! $dest ]]; then return 1; fi
274
275         if ! status_umts; then
276                 return 1;
277         fi
278
279         if ! check_who_locked $sliver; then
280                 return 1;
281         fi
282
283         if ip rule add to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then
284                 echo "$dest" >> $DESTS_FILE
285                 return 0
286         else 
287                 return 1        
288         fi
289         ip route flush cache  >/dev/null 2>&1
290 }
291
292 function del_destination(){
293         local dest="$1"
294         local sliver=$2
295         local sliver_nid=`get_nid $sliver`
296         local temp_nid=`get_temp_nid`
297
298         if [[ ! $dest ]]; then return 1; fi
299
300         if ! check_who_locked $sliver; then
301                 return 1;
302         fi
303
304         if ip rule del to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then
305                 return 0;
306         else 
307                 return 1;
308         fi
309         ip route flush cache  >/dev/null 2>&1
310 }
311
312
313 function get_ppp_address(){
314         ifconfig $PPP_INT | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1
315 }
316
317 function set_temp_nid(){
318         local sliver_nid=$1
319         local temp_nid=$((0x20000+$sliver_nid))
320         echo $temp_nid > $FILE_TEMP_NID
321 }
322
323
324 function check_who_locked(){
325         local sliver=$1
326         local sliver_nid=`get_nid $sliver`
327         local ret=0
328
329         if [ -e $LOCK_DIR ]; then
330                 if [[ `cat $FILE_LOCK_SLIVER` != $sliver_nid ]]; then
331                         echo "Interface in use by another slice.";
332                         ret=1
333                 fi
334         else
335                 ret=1
336         fi
337
338         return $ret
339
340 }
341
342 function kill_gcom(){
343         
344         killall $GCOMP
345         sleep 3
346         if ! ps -C $GCOMP >/dev/null 2>&1; then
347                 echo "$GCOMP terminated."       
348         else 
349                 echo "$GCOMP still alive. Try kill -9"
350                 sleep 2
351
352                 killall -9 $GCOMP
353         
354                 if ! ps -C $GCOMP >/dev/null 2>&1; then
355                         echo "$GCOMP terminated."
356                 else            
357                         echo "Couldn't stop $GCOMP. Please contact administrators for assistance."      
358                 fi
359         fi
360 }
361
362 function lock(){
363         local sliver=$1
364         local sliver_nid=`get_nid $sliver`
365         local ret=0
366
367         if [ -e $LOCK_DIR ]; then
368                 if ! check_who_locked $sliver; then
369                         ret=1
370                 fi
371         else 
372                 if mkdir $LOCK_DIR >/dev/null 2>&1; then
373                         echo "$sliver_nid" > $FILE_LOCK_SLIVER
374                 else
375                         ret=1
376                 fi
377         fi
378
379         return $ret
380 }
381
382 function unlock(){
383         local sliver=$1
384         local sliver_nid=`get_nid $sliver`
385         local ret=0
386
387         if ! [ -e $LOCK_DIR ]; then
388                 ret=1
389         else 
390                 if ! check_who_locked $sliver; then
391                         ret=1
392                 else
393                         if ! rmdir $LOCK_DIR; then
394                                 ret=1
395                         fi
396                 fi      
397         fi
398
399         return $ret
400 }
401
402
403
404
405 # checks ip addresses  
406 function valid_dotted_quad(){
407     oldIFS=$IFS
408     IFS=.
409     set -f
410     set -- $1
411     if [ $# -eq 4 ]
412     then
413       for seg
414       do
415         case $seg in
416             ""|*[!0-9]*) return 1; break ;; ## Segment empty or non-numeric char
417             *) [ $seg -gt 255 ] && return 2 ;;
418         esac
419       done
420     else
421       return 3 ## Not 4 segments
422     fi
423     IFS=$oldIFS
424     set +f
425     return 0;
426 }
427