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