#! /bin/sh
#############################################################################
# Copyright (C) 2012 Laboratório de Sistemas e Tecnologia Subaquática       #
# Departamento de Engenharia Electrotécnica e de Computadores               #
# Rua Dr. Roberto Frias, 4200-465 Porto, Portugal                           #
#############################################################################
# Author: Ricardo Martins                                                   #
#############################################################################

GSM_USER='vodafone'
GSM_PASS='vodafone'
GSM_APN='internet.vodafone.pt'
GSM_MODE='AT\^SYSCFG=2,2,3fffffff,0,1'
GSM_PIN='AT'

FWL_EXT_ITF='ppp0'
FWL_INT_ITF='eth0'

CHAT_SCRIPT=$(cat <<EOF
ABORT 'BUSY' \
ABORT 'NO CARRIER' \
ABORT 'VOICE' \
ABORT 'NO DIALTONE' \
ABORT 'NO DIAL TONE' \
ABORT 'NO ANSWER' \
ABORT 'DELAYED' \
REPORT CONNECT \
TIMEOUT 6 \
'' 'ATQ0' \
'OK-AT-OK' 'ATZ' \
TIMEOUT 3 \
'OK' '$GSM_PIN' \
'OK-AT-OK' 'ATI' \
'OK' 'ATZ' \
'OK' 'ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0' \
'OK' '$GSM_MODE' \
'OK-AT-OK' 'AT+CGDCONT=1,\"IP\",\"$GSM_APN\"' \
'OK' 'ATDT*99***1#' \
TIMEOUT 30 \
CONNECT ''
EOF
)

modem_probe()
{
    nr="$(cat /proc/tty/driver/usbserial | grep GSM | head -n 1 | cut -f1 -d:)"
    if [ -z "$nr" ]; then
        echo ""
    else
        echo "/dev/ttyUSB$nr"
    fi
}

ppp_start()
{
    modem="$(modem_probe)"

    if [ -z "$modem" ]; then
        echo -e "\nERROR: failed to find GSM modem.\n"
        exit 1
    fi

    auth=''
    if [ -n "$GSM_USER" ] && [ -n "$GSM_PASS" ]; then
        auth="user \"$GSM_USER\" password \"$GSM_PASS\""
    fi

    echo -e "\n* Removing default route"

    /sbin/route del default dev eth0 > /dev/null 2>&1

    echo -e "\n* Starting PPP"

    /usr/sbin/pppd \
        "$modem" \
        921600 \
        $auth \
        lock \
        crtscts \
        modem \
        passive \
        novj \
        defaultroute \
        noipdefault \
        usepeerdns \
        noauth \
        hide-password \
        persist \
        holdoff 10 \
        maxfail 2 \
        updetach \
        connect "/usr/sbin/chat -E -v -t15 $CHAT_SCRIPT" > /var/run/ppp.log 2>&1

    if [ $? -ne 0 ]; then
        echo -e "\nERROR: PPP failed to establish a connection.\n"
        exit 1
    fi

    ip=$(ifconfig ppp0 | grep inet | cut -f2 -d: | cut -f1 -d' ')
    echo "  - External IP is $ip"
}

ppp_stop()
{
    pid="$(cat /var/run/ppp0.pid 2> /dev/null)"

    echo -e "\n* Stopping PPP"

    if [ -z "$pid" ]; then
        echo "  - Daemon is not running"
        return 0
    fi

    for n in 1 2 3 4 5; do
        if ! [ -d "/proc/$pid" ]; then
            echo "  - Daemon stopped"
            return 0
        fi

        echo "  - Sending SIGTERM to '$pid' (try $n)"
        kill "$pid" > /dev/null 2>&1
        sleep 2
    done

    kill -9 "$pid" > /dev/null 2>&1
    echo "  - Daemon terminated"
    return 0
}

nat_start()
{
    echo -e "\n* Enabling NAT"

    echo "  - Enabling IP forwarding"
    echo '1' > /proc/sys/net/ipv4/ip_forward
    echo '1' > /proc/sys/net/ipv4/ip_dynaddr

    echo "  - Flushing rules"
    iptables -P INPUT ACCEPT
    iptables -F INPUT
    iptables -P OUTPUT ACCEPT
    iptables -F OUTPUT
    iptables -P FORWARD DROP
    iptables -F FORWARD
    iptables -t nat -F

    echo "  - Installing rules"
    iptables -A FORWARD -i "$FWL_EXT_ITF" -o "$FWL_INT_ITF" -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -i "$FWL_EXT_ITF" -o "$FWL_EXT_ITF" -j ACCEPT
    iptables -A FORWARD -i "$FWL_EXT_ITF" -o "$FWL_INT_ITF" -j ACCEPT
    iptables -A FORWARD -i "$FWL_INT_ITF" -o "$FWL_EXT_ITF" -j ACCEPT
    iptables -A FORWARD -j LOG
    iptables -t nat -A POSTROUTING -o "$FWL_EXT_ITF" -j MASQUERADE
}

nat_stop()
{
    echo -e "\n* Disabling NAT"

    echo "  - Disabling IP forwarding"
    echo '0' > /proc/sys/net/ipv4/ip_forward
    echo '0' > /proc/sys/net/ipv4/ip_dynaddr

    echo "  - Flushing NAT rules"
    iptables -P INPUT ACCEPT
    iptables -F INPUT
    iptables -P OUTPUT ACCEPT
    iptables -F OUTPUT
    iptables -P FORWARD DROP
    iptables -F FORWARD
    iptables -t nat -F
}

start()
{
    ppp_start && nat_start
    if [ $? -eq 0 ]; then
        echo -e "\n* Connection Established\n"
    else
        echo -e "\nERROR: failed to establish a connection\n"
    fi
}

stop()
{
    nat_stop && ppp_stop
    if [ $? -eq 0 ]; then
        echo -e "\n* Service stopped\n"
    else
        echo -e "\nERROR: failed to stop service.\n"
    fi
}