#!/bin/bash STROK="remote IP address" GCOMP="comgt" GCOM="/usr/bin/"${GCOMP} LOGF="/tmp/umtslogs" PPPD_PIDFILE="/var/run/umts_pppd.pid" DESTS_FILE="/tmp/umts_dest_file" FILE_TEMP_NID="/tmp/umts_temp_nid" FILE_UMTS_INT="/tmp/umts_dev" LOCK_DIR="/tmp/umts_lock_d" FILE_LOCK_SLIVER="/tmp/umts_locking_sliver" PPP_INT="ppp0" PPPD="pppd" CHAT_SCRIPTS="/etc/chatscripts" UMTS_CONF="/etc/umts.conf" function get_umts_dev(){ echo "/dev/umts_modem" } function init_umts(){ #local found=1 if [ -e $LOCK_DIR ]; then rmdir $LOCK_DIR fi #if ! grep "umts_table" /etc/iproute2/rt_tables > /dev/null 2>&1; then # echo "20 umts_table" >> /etc/iproute2/rt_tables #fi return 0 } function get_temp_nid(){ cat $FILE_TEMP_NID } #called when the connection is started function conn_on(){ local sliver=$1 #DESTS_FILE contains added destinations rm -f $DESTS_FILE set_temp_nid $sliver_nid set_routes $sliver cat $LOGF | grep "local" return 0 } #called when the connection is terminated function conn_off(){ local sliver=$1 local ppp_addr=$2 unset_routes $sliver $ppp_addr for i in `cat $DESTS_FILE`; do del_destination $i $sliver > /dev/null 2>&1 done rm $DESTS_FILE >/dev/null 2>&1 } function start_umts(){ local sliver=$1 local sliver_nid=`get_nid $sliver` if ! grep "umts_table" /etc/iproute2/rt_tables > /dev/null 2>&1; then echo "20 umts_table" >> /etc/iproute2/rt_tables fi if ! lock $sliver; then return 1 fi if status_umts; then echo "Already connected" return 0; fi echo "Starting GCOM..." if ! $GCOM -d `get_umts_dev`; then unlock $sliver return 1 fi rm -f $LOGF if [ -e $UMTS_CONF ]; then . $UMTS_CONF fi if ! [[ $APN ]]; then APN="web.omnitel.it" fi if ! [[ $NUM ]]; then NUM="*99***1#" fi exec /usr/sbin/pppd nodetach `get_umts_dev` 460800 \ 0.0.0.0:0.0.0.0 \ connect "/usr/sbin/chat -v \ TIMEOUT 6 \ ABORT '\nBUSY\r' \ ABORT '\nNO ANSWER\r' \ ABORT '\nRINGING\r\n\r\nRINGING\r' \ '' ATZ OK 'ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0' OK \ 'AT+CGDCONT=1,\"IP\",\"$APN\"' OK \ ATD$NUM CONNECT ''" > $LOGF & echo $! > $PPPD_PIDFILE sleep 5s; #waiting for the interface to establish the link if grep "$STROK" $LOGF >/dev/null 2>&1; then conn_on $sliver $sliver_nid else #second try sleep 5s; if grep "$STROK" $LOGF >/dev/null 2>&1; then conn_on $sliver $sliver_nid else stop_umts $sliver return 1 fi fi } function stop_umts(){ local sliver=$1 local sliver_nid=`get_nid $sliver` local ppp_addr if ! [ -e $PPPD_PIDFILE ]; then echo "Disconnected" return 0; fi ppp_addr=`get_ppp_address` if ! check_who_locked $sliver; then return 1 fi PID=`cat $PPPD_PIDFILE`; if [ -d /proc/$PID ] && grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then kill $PID; touch $DESTS_FILE sleep 2s; fi if status_umts; then return 1; else conn_off $sliver $ppp_addr cat $LOGF | grep "time" rm $PPPD_PIDFILE unlock $sliver; return 0 fi } function status_umts(){ local sliver=$1 if ! [ -e $PPPD_PIDFILE ]; then return 1; fi PID=`cat $PPPD_PIDFILE` if [ -d /proc/$PID ] && grep $PPPD /proc/$PID/cmdline >/dev/null 2>&1; then return 0; else return 1; fi } #add the ppp interface to the slice - not used at the moment function add_interface(){ local nid=`get_nid $1` $NADDRESS --add --nid $nid --ip $PPP_INT >>$LOGFILE 2>&1; } #remove the ppp interface from the slice - not used at the moment function del_interface(){ local nid=`get_nid $1` #$NADDRESS --remove --nid $NID --ip $PPP_INT >>$LOGFILE 2>&1; } #get slice network id function get_nid(){ id -u ${1} } function set_routes(){ local sliver=$1 local sliver_nid=`get_nid $sliver` local temp_nid=`get_temp_nid` local ppp_addr=`get_ppp_address` #Asks VNET+ to tag all the packets with the respective sliver id iptables -t mangle -A OUTPUT -j MARK --copy-xid 0x00 #Changes the netfilter mark of packets to trigger rerouting. #We need to change the mark because the kernel triggers the rerouting process only #if it sees that the netfilter mark has been altered in the mangle iptables chain iptables -t mangle -A OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid #Adds an SNAT rule to set the source IP address of packets that are about to go out through the UMTS #interface. The kernel sets the source address of packets when the first routing process happens #so, without this rule, packets would have the source ip address set on the first routing process of the ethernet interface iptables -t nat -A POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr #Restores the original netfilter mark for planetflow iptables -t mangle -I POSTROUTING 1 -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid #Forbids other slices to use the UMTS interface iptables -t mangle -I POSTROUTING 2 -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP #Enables the explicit bind to the UMTS interface. Applications launched by the user in the slice that is using the UMTS and that #bind to the UMTS interface will have packets going out through the UMTS interface ip route flush table umts_table >/dev/null 2>&1 ip rule add from $ppp_addr fwmark $temp_nid table umts_table >/dev/null 2>&1 ip route add default dev $PPP_INT src $ppp_addr table umts_table >/dev/null 2>&1 ip route flush cache >/dev/null 2>&1 } function unset_routes(){ local sliver=$1 local ppp_addr=$2 local sliver_nid=`get_nid $sliver` local temp_nid=`get_temp_nid` #removing the rules for changing the mark and the rules for SNAT iptables -t mangle -D OUTPUT -j MARK --copy-xid 0x00 iptables -t mangle -D OUTPUT -m mark --mark $sliver_nid -j MARK --set-mark $temp_nid iptables -t nat -D POSTROUTING -o $PPP_INT -j SNAT --to-source $ppp_addr iptables -t mangle -D POSTROUTING -m mark --mark $temp_nid -j MARK --set-mark $sliver_nid iptables -t mangle -D POSTROUTING -o $PPP_INT -m mark ! --mark $sliver_nid -j DROP #disable the explicit bind to the ppp interface ip rule del from $ppp_addr fwmark $temp_nid table umts_table >/dev/null 2>&1 ip route del default dev $PPP_INT src $ppp_addr table umts_table >/dev/null 2>&1 ip route flush cache >/dev/null 2>&1 } function add_destination(){ local dest="$1" local sliver=$2 local sliver_nid=`get_nid $sliver` local temp_nid=`get_temp_nid` if [[ ! $dest ]]; then return 1; fi if ! status_umts; then return 1; fi if ! check_who_locked $sliver; then return 1; fi if ip rule add to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then echo "$dest" >> $DESTS_FILE return 0 else return 1 fi ip route flush cache >/dev/null 2>&1 } function del_destination(){ local dest="$1" local sliver=$2 local sliver_nid=`get_nid $sliver` local temp_nid=`get_temp_nid` if [[ ! $dest ]]; then return 1; fi if ! check_who_locked $sliver; then return 1; fi if ip rule del to "$dest" fwmark $temp_nid table umts_table >/dev/null 2>&1; then return 0; else return 1; fi ip route flush cache >/dev/null 2>&1 } function get_ppp_address(){ ifconfig $PPP_INT | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1 } function set_temp_nid(){ local sliver_nid=$1 local temp_nid=$((0x20000+$sliver_nid)) echo $temp_nid > $FILE_TEMP_NID } function check_who_locked(){ local sliver=$1 local sliver_nid=`get_nid $sliver` local ret=0 if [ -e $LOCK_DIR ]; then if [[ `cat $FILE_LOCK_SLIVER` != $sliver_nid ]]; then echo "Interface in use by another slice."; ret=1 fi else ret=1 fi return $ret } function kill_gcom(){ killall $GCOMP sleep 3 if ! ps -C $GCOMP >/dev/null 2>&1; then echo "$GCOMP terminated." else echo "$GCOMP still alive. Try kill -9" sleep 2 killall -9 $GCOMP if ! ps -C $GCOMP >/dev/null 2>&1; then echo "$GCOMP terminated." else echo "Couldn't stop $GCOMP. Please contact administrators for assistance." fi fi } function lock(){ local sliver=$1 local sliver_nid=`get_nid $sliver` local ret=0 if [ -e $LOCK_DIR ]; then if ! check_who_locked $sliver; then ret=1 fi else if mkdir $LOCK_DIR >/dev/null 2>&1; then echo "$sliver_nid" > $FILE_LOCK_SLIVER else ret=1 fi fi return $ret } function unlock(){ local sliver=$1 local sliver_nid=`get_nid $sliver` local ret=0 if ! [ -e $LOCK_DIR ]; then ret=1 else if ! check_who_locked $sliver; then ret=1 else if ! rmdir $LOCK_DIR; then ret=1 fi fi fi return $ret } # checks ip addresses function valid_dotted_quad(){ oldIFS=$IFS IFS=. set -f set -- $1 if [ $# -eq 4 ] then for seg do case $seg in ""|*[!0-9]*) return 1; break ;; ## Segment empty or non-numeric char *) [ $seg -gt 255 ] && return 2 ;; esac done else return 3 ## Not 4 segments fi IFS=$oldIFS set +f return 0; }