#!/bin/bash
#
# .---.                  .              .
# |                      |              |
# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
#
#                    Freedom in the Cloud
#
# Used to enable or disable batman mesh protocol on wlanX
#
# License
# =======
#
# Copyright (C) 2015-2018 Bob Mottram <bob@freedombone.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

PROJECT_NAME='freedombone'
COMPLETION_FILE=/root/${PROJECT_NAME}-completed.txt

# hotspot passphrase must be 5 characters or longer
HOTSPOT_PASSPHRASE="${PROJECT_NAME}"

source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-wifi
source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-mesh

mesh_protocol_init
update_wifi_adaptors

if [ ! $IFACE ]; then
    echo $'No wlan adaptor'
    exit 0
fi

if [ -e /etc/default/batctl ]; then
    . /etc/default/batctl
fi

function status {
    batctl o

    if grep -q "bmx6" $MESH_CURRENT_PROTOCOL; then
        bmx6 -c show=originators
    fi
    if grep -q "bmx7" $MESH_CURRENT_PROTOCOL; then
        bmx7 -c show=originators
    fi
}

function stop {
    if [ ! -f $MESH_CURRENT_PROTOCOL ]; then
        return
    fi

    if [ -z "$IFACE" ]; then
        echo 'error: unable to find wifi interface, not enabling batman-adv mesh'
        return
    fi

    systemctl stop bmx6
    systemctl stop bmx7
    systemctl stop olsr2
    systemctl stop babel
    systemctl disable bmx6
    systemctl disable bmx7
    systemctl disable olsr2
    systemctl disable babel
    systemctl stop dnsmasq
    systemctl disable dnsmasq

    if [ "$EIFACE" ]; then
        brctl delif $BRIDGE bat0
        ifconfig $BRIDGE down || true
        ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier)
        if [[ "$ethernet_connected" != "0" ]]; then
            systemctl stop hostapd
            brctl delif $BRIDGE $EIFACE
            ifconfig $EIFACE down -promisc
        fi
        brctl delbr $BRIDGE
    fi

    ifconfig bat0 down -promisc

    batctl if del $IFACE
    ifconfig $IFACE mtu 1500
    ifconfig $IFACE down
    iwconfig $IFACE mode managed

    if [ $IFACE_SECONDARY ]; then
        systemctl stop hostapd
        systemctl disable hostapd
        batctl if del $IFACE_SECONDARY
        ifconfig $IFACE_SECONDARY mtu 1500
        ifconfig $IFACE_SECONDARY down
        iwconfig $IFACE_SECONDARY mode managed
    fi

    rmmod batman-adv

    disable_mesh_firewall

    systemctl restart network-manager

    if [ -f $MESH_CURRENT_PROTOCOL ]; then
        rm $MESH_CURRENT_PROTOCOL
    fi
}

function verify {
    tempfile="$(mktemp)"
    batctl o > $tempfile
    if grep -q "disabled" $tempfile; then
        echo $'B.A.T.M.A.N. not enabled'
        rm $tempfile
        stop
        exit 726835
    fi
    echo $'B.A.T.M.A.N. is running'
    rm $tempfile
}

function add_wifi_interface {
    ifname=$1
    ifssid=$WIFI_SSID
    if [ $2 ]; then
        ifssid=$2
    fi
    ifmode=ad-hoc
    if [ $3 ]; then
        ifmode=$3
    fi
    ifchannel=$CHANNEL
    if [ $4 ]; then
        ifchannel=$4
    fi

    ifconfig $ifname down
    ifconfig $ifname mtu 1532
    peermac=$(assign_peer_address)
    if [ ! $peermac ]; then
        echo $"Unable to obtain MAC address for $peermac on $ifname"
        return
    fi
    ifconfig $ifname hw ether $peermac
    echo $"$ifname assigned MAC address $peermac"
    iwconfig $ifname enc off
    iwconfig $ifname mode $ifmode essid $ifssid channel $ifchannel

    batctl if add $ifname
    ifconfig $ifname up
}

function start {
    update_wifi_adaptors

    if [ -z "$IFACE" ] ; then
        echo 'error: unable to find wifi interface, not enabling batman-adv mesh'
        exit 723657
    fi
    echo "info: enabling batman-adv mesh network $WIFI_SSID on $IFACE"

    stop
    systemctl stop network-manager
    sleep 5

    systemctl stop dnsmasq
    systemctl disable dnsmasq

    # remove an avahi service which isn't used
    if [ -f /etc/avahi/services/udisks.service ]; then
        sudo rm /etc/avahi/services/udisks.service
    fi

    global_rate_limit

    # Might have to re-enable wifi
    rfkill unblock $(rfkill list|awk -F: "/phy/ {print $1}") || true

    secondary_wifi_available=
    if [ $IFACE_SECONDARY ]; then
        if [[ $IFACE != $IFACE_SECONDARY ]]; then
            if [ -d /etc/hostapd ]; then
                if [ ${#HOTSPOT_PASSPHRASE} -gt 4 ]; then
                    secondary_wifi_available=1
                else
                    echo $'Hotspot passphrase is too short'
                fi
            fi
        fi
    fi

    modprobe batman-adv

    # avahi on ipv6
    sed -i 's|use-ipv4=.*|use-ipv4=no|g' /etc/avahi/avahi-daemon.conf
    sed -i 's|use-ipv6=.*|use-ipv6=yes|g' /etc/avahi/avahi-daemon.conf

    sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx6 dev=${IFACE}|g" /etc/systemd/system/bmx6.service
    sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx7 dev=${IFACE}|g" /etc/systemd/system/bmx7.service
    sed -i "s|ExecStart=.*|ExecStart=/usr/local/sbin/olsrd2_static ${IFACE}|g" /etc/systemd/system/olsr2.service
    sed -i "s|ExecStart=.*|ExecStart=/usr/local/bin/babeld ${IFACE}|g" /etc/systemd/system/babel.service
    systemctl daemon-reload

    add_wifi_interface $IFACE $WIFI_SSID ad-hoc $CHANNEL

    # NOTE: Don't connect the secondary wifi device. hostapd will handle that by itself

    ifconfig bat0 up promisc

    brctl addbr $BRIDGE
    brctl addif $BRIDGE bat0
    ifconfig bat0 0.0.0.0
    ethernet_connected='0'
    if [ "$EIFACE" ] ; then
        ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier)
        if [[ "$ethernet_connected" != "0" ]]; then
            echo $'Trying ethernet bridge to the internet'
            brctl addif $BRIDGE $EIFACE
            ifconfig $EIFACE 0.0.0.0
            ifconfig $EIFACE up promisc
            echo $'End of ethernet bridge'

            sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx6 dev=${IFACE} dev=${EIFACE}|g" /etc/systemd/system/bmx6.service
            sed -i "s|ExecStart=.*|ExecStart=/usr/sbin/bmx7 dev=${IFACE} dev=${EIFACE}|g" /etc/systemd/system/bmx7.service
            sed -i "s|ExecStart=.*|ExecStart=/usr/local/sbin/olsrd2_static ${IFACE} ${EIFACE}|g" /etc/systemd/system/olsr2.service
            sed -i "s|ExecStart=.*|ExecStart=/usr/local/bin/babeld ${IFACE} ${EIFACE}|g" /etc/systemd/system/babel.service
            systemctl daemon-reload
        else
            echo $"$EIFACE is not connected"
        fi
    fi
    ifconfig $BRIDGE up
    dhclient $BRIDGE

    enable_mesh_seconary_wifi

    enable_mesh_firewall

    enable_mesh_scuttlebot
    enable_mesh_tor

    sed -i "s|server_name .*|server_name ${HOSTNAME}.local;|g" /etc/nginx/sites-available/git_ssb

    systemctl restart nginx

    if [ ! -f $MESH_DEFAULT_PROTOCOL ]; then
        echo 'bmx6' > $MESH_DEFAULT_PROTOCOL
    fi

    if grep -q "bmx6" $MESH_DEFAULT_PROTOCOL; then
        systemctl enable bmx6
        systemctl restart bmx6
        sed -i 's|<type>.*|<type>_bmx6._tcp</type>|g' /etc/avahi/services/routing.service
    fi

    if grep -q "bmx7" $MESH_DEFAULT_PROTOCOL; then
        systemctl enable bmx7
        systemctl restart bmx7
        sed -i 's|<type>.*|<type>_bmx7._tcp</type>|g' /etc/avahi/services/routing.service
    fi

    if grep -q "olsr" $MESH_DEFAULT_PROTOCOL; then
        IFACE=$(cat /etc/systemd/system/olsr2.service | grep ExecStart | awk -F ' ' '{print $2}')
        mesh_generate_ipv6_address $IFACE

        systemctl enable olsr2
        systemctl restart olsr2
        sed -i 's|<type>.*|<type>_olsr2._tcp</type>|g' /etc/avahi/services/routing.service
    fi

    if grep -q "babel" $MESH_DEFAULT_PROTOCOL; then
        IFACE=$(cat /etc/systemd/system/babel.service | grep ExecStart | awk -F ' ' '{print $2}')
        mesh_generate_ipv6_address $IFACE

        systemctl enable babel
        systemctl restart babel
        sed -i 's|<type>.*|<type>_babel._tcp</type>|g' /etc/avahi/services/routing.service
    fi

    systemctl restart avahi-daemon

    verify

    echo "$(cat $MESH_DEFAULT_PROTOCOL)" > $MESH_CURRENT_PROTOCOL
}

function monitor {
    if [ -z "$IFACE" ] ; then
        echo 'error: unable to find wifi interface, not enabling batman-adv mesh'
        exit 723657
    fi

    clear
    echo ''
    echo $'*** Stopping network ***'
    echo ''

    stop

    echo "info: monitoring mesh network $WIFI_SSID on $IFACE"

    systemctl stop network-manager
    sleep 5

    clear
    echo ''
    echo $'*** Setting firewall rate limit ***'
    echo ''

    global_rate_limit

    clear
    echo ''
    echo $'*** Enabling wifi adaptor in monitor mode ***'
    echo ''

    # Might have to re-enable wifi
    rfkill unblock $(rfkill list|awk -F: "/phy/ {print $1}") || true

    ifconfig $IFACE down
    ifconfig $IFACE mtu 1532
    ifconfig $IFACE hw ether $(assign_peer_address)
    iwconfig $IFACE enc off
    iwconfig $IFACE mode monitor channel $CHANNEL
    sleep 1
    iwconfig $IFACE ap $CELLID

    modprobe batman-adv
    batctl if add $IFACE
    ifconfig $IFACE up

    horst -i $IFACE

    clear
    echo ''
    echo $'*** Restarting the network daemon. This may take a while. ***'
    echo ''

    start
}

if ! grep -q "$IFACE" /proc/net/dev; then
    echo 'Interface $IFACE was not found'
    stop
    exit 1
fi

case "$1" in
    start|stop|status|monitor)
        $1
        ;;
    restart)
        clear
        echo ''
        echo $'*** Stopping mesh network connection ***'
        echo ''
        stop
        sleep 10
        clear
        echo ''
        echo $'*** Starting mesh network connection ***'
        echo ''
        start
        ;;
    ping)
        batctl ping $2
        ;;
    data)
        watch -n1 "batctl s | grep mgmt | grep bytes"
        ;;
    ls|list)
        avahi-browse -atl
        ;;
    *)
        echo "error: invalid parameter $1"
        echo 'usage: $0 {start|stop|restart|status|ping|ls|list}'
        exit 2
        ;;
esac
exit 0
