small change in doc; some files renamed: umts_backend -> umtsd
[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="/tmp/umts_lock_d"
13 FILE_LOCK_SLIVER="/tmp/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     echo $! > $PPPD_PIDFILE
125
126     sleep 5s;  #waiting for the interface to establish the link
127     if grep "$STROK" $LOGF >/dev/null 2>&1; then
128         conn_on $sliver $sliver_nid
129     else
130         #second try
131         sleep 5s;
132         if grep "$STROK" $LOGF >/dev/null 2>&1; then
133             conn_on $sliver $sliver_nid
134         else
135             stop_umts $sliver
136             return 1
137         fi
138     fi
139 }
140
141
142 function stop_umts(){
143     local sliver=$1
144     local sliver_nid=`get_nid $sliver`
145     local ppp_addr
146
147     if ! [ -e $PPPD_PIDFILE ]; then 
148         echo "Disconnected"
149         return 0;
150     fi
151
152     ppp_addr=`get_ppp_address`
153
154     if ! check_who_locked $sliver; then
155         return 1
156     fi
157
158     PID=`cat $PPPD_PIDFILE`;
159
160     if [ -d /proc/$PID ] &&  grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then        
161         kill $PID;      touch $DESTS_FILE
162
163         sleep 2s;
164     fi
165
166     if status_umts; then
167         return 1;
168     else
169         conn_off $sliver $ppp_addr
170         cat $LOGF | grep "time"
171         rm $PPPD_PIDFILE
172         unlock $sliver;
173         return 0
174     fi
175 }
176
177
178 function status_umts(){
179     local sliver=$1
180         
181     if ! [ -e $PPPD_PIDFILE ]; then return 1; fi
182     PID=`cat $PPPD_PIDFILE`
183
184     if [ -d /proc/$PID ] &&  grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then
185         return 0;
186     else 
187         return 1;
188     fi
189 }
190
191 #add the ppp interface to the slice - not used at the moment
192 function add_interface(){
193     local nid=`get_nid $1`
194     $NADDRESS --add --nid $nid --ip $PPP_INT >>$LOGFILE 2>&1;
195 }
196
197 #remove the ppp interface from the slice - not used at the moment
198 function del_interface(){
199     local nid=`get_nid $1`
200     #$NADDRESS --remove --nid $NID --ip $PPP_INT >>$LOGFILE 2>&1;
201 }
202
203 #get slice network id
204 function get_nid(){
205     id -u ${1}
206 }
207
208 function set_routes(){
209         local sliver=$1
210         local sliver_nid=`get_nid $sliver`
211         local temp_nid=`get_temp_nid`
212         local ppp_addr=`get_ppp_address`
213
214         #Asks VNET+ to tag all the packets with the respective sliver id
215         iptables -t mangle -A OUTPUT -j MARK --copy-xid 0x00
216
217         #Changes the netfilter mark of packets to trigger rerouting. 
218         #We need to change the mark because the kernel triggers the rerouting process only
219         #if it sees that the netfilter mark has been altered in the mangle iptables chain
220         iptables -t mangle -A OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid
221
222         #Adds an SNAT rule to set the source IP address of packets that are about to go out through the UMTS
223         #interface. The kernel sets the source address of packets when the first routing process happens
224         #so, without this rule, packets would have the source ip address set on the first routing process of the ethernet interface
225         iptables -t nat -A POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr
226         
227         #Restores the original netfilter mark for planetflow
228         iptables -t mangle -I POSTROUTING 1 -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid
229
230         #Forbids other slices to use the UMTS interface
231         iptables -t mangle -I POSTROUTING 2 -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP
232         
233         #Enables the explicit bind to the UMTS interface. Applications launched by the user in the slice that is using the UMTS and that
234         #bind to the UMTS interface will have packets going out through the UMTS interface 
235         ip route flush table umts_table >/dev/null 2>&1 
236         ip rule add from $ppp_addr fwmark $temp_nid table umts_table >/dev/null 2>&1
237         ip route add default dev $PPP_INT src $ppp_addr table umts_table >/dev/null 2>&1
238         ip route flush cache  >/dev/null 2>&1
239 }
240
241 function unset_routes(){
242         local sliver=$1
243         local ppp_addr=$2
244         local sliver_nid=`get_nid $sliver`
245         local temp_nid=`get_temp_nid`
246         
247
248         #removing the rules for changing the mark and the rules for SNAT 
249         iptables -t mangle -D OUTPUT -j MARK --copy-xid 0x00
250         iptables -t mangle -D OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid
251         iptables -t nat -D POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr
252         iptables -t mangle -D POSTROUTING -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid
253
254         iptables -t mangle -D POSTROUTING -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP
255
256         #disable the explicit bind to the ppp interface
257         ip rule del from $ppp_addr fwmark $temp_nid table umts_table  >/dev/null 2>&1
258         ip route del default dev $PPP_INT  src $ppp_addr table umts_table >/dev/null 2>&1
259         ip route flush cache  >/dev/null 2>&1
260
261 }
262
263 function add_destination(){
264         local dest="$1"
265         local sliver=$2
266         local sliver_nid=`get_nid $sliver`
267         local temp_nid=`get_temp_nid`
268
269         if [[ ! $dest ]]; then return 1; fi
270
271         if ! status_umts; then
272                 return 1;
273         fi
274
275         if ! check_who_locked $sliver; then
276                 return 1;
277         fi
278
279         if ip rule add to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then
280                 echo "$dest" >> $DESTS_FILE
281                 return 0
282         else 
283                 return 1        
284         fi
285         ip route flush cache  >/dev/null 2>&1
286 }
287
288 function del_destination(){
289         local dest="$1"
290         local sliver=$2
291         local sliver_nid=`get_nid $sliver`
292         local temp_nid=`get_temp_nid`
293
294         if [[ ! $dest ]]; then return 1; fi
295
296         if ! check_who_locked $sliver; then
297                 return 1;
298         fi
299
300         if ip rule del to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then
301                 return 0;
302         else 
303                 return 1;
304         fi
305         ip route flush cache  >/dev/null 2>&1
306 }
307
308
309 function get_ppp_address(){
310         ifconfig $PPP_INT | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1
311 }
312
313 function set_temp_nid(){
314         local sliver_nid=$1
315         local temp_nid=$((0x20000+$sliver_nid))
316         echo $temp_nid > $FILE_TEMP_NID
317 }
318
319
320 function check_who_locked(){
321         local sliver=$1
322         local sliver_nid=`get_nid $sliver`
323         local ret=0
324
325         if [ -e $LOCK_DIR ]; then
326                 if [[ `cat $FILE_LOCK_SLIVER` != $sliver_nid ]]; then
327                         echo "Interface in use by another slice.";
328                         ret=1
329                 fi
330         else
331                 ret=1
332         fi
333
334         return $ret
335
336 }
337
338 function kill_gcom(){
339         
340         killall $GCOMP
341         sleep 3
342         if ! ps -C $GCOMP >/dev/null 2>&1; then
343                 echo "$GCOMP terminated."       
344         else 
345                 echo "$GCOMP still alive. Try kill -9"
346                 sleep 2
347
348                 killall -9 $GCOMP
349         
350                 if ! ps -C $GCOMP >/dev/null 2>&1; then
351                         echo "$GCOMP terminated."
352                 else            
353                         echo "Couldn't stop $GCOMP. Please contact administrators for assistance."      
354                 fi
355         fi
356 }
357
358 function lock(){
359         local sliver=$1
360         local sliver_nid=`get_nid $sliver`
361         local ret=0
362
363         if [ -e $LOCK_DIR ]; then
364                 if ! check_who_locked $sliver; then
365                         ret=1
366                 fi
367         else 
368                 if mkdir $LOCK_DIR >/dev/null 2>&1; then
369                         echo "$sliver_nid" > $FILE_LOCK_SLIVER
370                 else
371                         ret=1
372                 fi
373         fi
374
375         return $ret
376 }
377
378 function unlock(){
379         local sliver=$1
380         local sliver_nid=`get_nid $sliver`
381         local ret=0
382
383         if ! [ -e $LOCK_DIR ]; then
384                 ret=1
385         else 
386                 if ! check_who_locked $sliver; then
387                         ret=1
388                 else
389                         if ! rmdir $LOCK_DIR; then
390                                 ret=1
391                         fi
392                 fi      
393         fi
394
395         return $ret
396 }
397
398
399
400
401 # checks ip addresses  
402 function valid_dotted_quad(){
403     oldIFS=$IFS
404     IFS=.
405     set -f
406     set -- $1
407     if [ $# -eq 4 ]
408     then
409       for seg
410       do
411         case $seg in
412             ""|*[!0-9]*) return 1; break ;; ## Segment empty or non-numeric char
413             *) [ $seg -gt 255 ] && return 2 ;;
414         esac
415       done
416     else
417       return 3 ## Not 4 segments
418     fi
419     IFS=$oldIFS
420     set +f
421     return 0;
422 }
423