#!/bin/bash
### BEGIN INIT INFO
# Provides: ynh-piratebox
# Required-Start:    $network $remote_fs $syslog ynh-hotspot
# Required-Stop:     $network $remote_fs $syslog ynh-hotspot
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Set prerequisites for wifi piratebox.
# Description:       Set prerequisites for wifi piratebox.
### END INIT INFO

# PirateBox app for YunoHost 
# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
# Contribute at https://github.com/jvaubourg/piratebox_ynh
# 
# 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/>.

# Functions
## State functions

has_hotspot_app() {
  [ -e /tmp/.ynh-hotspot-started ]
}

is_nat4_dns_set() {
  iptables -nvt nat -L PREROUTING | grep 'udp dpt:53' | grep -q "${ynh_wifi_device}" \
  && iptables -nvt nat -L POSTROUTING | grep MASQUERADE | grep -q "${ynh_wifi_device}"
}

is_nat4_web_set() {
  iptables -nvt nat -L PREROUTING | grep 'tcp dpt:80' | grep -q "${ynh_wifi_device}"
}

is_filt4_nohttps_set() {
  iptables -nv -L INPUT | grep 'tcp dpt:443 reject' | grep -q "${ynh_wifi_device}"
}

is_filt4_nofwd_set() {
  iptables -nv -L FORWARD | grep 'reject-with' | grep -q "${ynh_wifi_device}"
}

is_fakedns_running() {
  ps aux | grep -v grep | grep -q piratebox_fakedns
}

is_running() {
  has_hotspot_app \
  && is_nat4_dns_set && is_nat4_web_set \
  && is_filt4_nohttps_set && is_filt4_nofwd_set \
  && is_captive_set \
  && is_fakedns_running
}

is_captive_set() {
  ls /etc/nginx/conf.d/captive-piratebox.conf &> /dev/null
}

## Setters

# The IPv6 NAT features are not available available before the kernel 3.8
# therefore the IPv6-compliance will be add when Debian Stable has a
# compliant kernel

set_nat4_dns() {
  iptables -t nat -A PREROUTING -i "${ynh_wifi_device}" -p udp --dport 53 -j DNAT --to-destination "${ynh_ip4_nat_prefix}.1:4253"
  iptables -t nat -A POSTROUTING -o "${ynh_wifi_device}" -j MASQUERADE
}

set_nat4_web() {
  iptables -t nat -A PREROUTING -i "${ynh_wifi_device}" -p tcp --dport 80 -j REDIRECT --to-port 4280
}

set_filt4_nohttps() {
  iptables -I INPUT 1 -i "${ynh_wifi_device}" -p tcp --dport 443 -j REJECT
}

set_filt4_nofwd() {
  iptables -I FORWARD 1 -j REJECT -i "${ynh_wifi_device}"
}

set_captive() {
  cp /var/www/piratebox/config.{tpl.,}php

  sed -i "s|<TPL:OPT_NAME>|${ynh_opt_name}|" -i /var/www/piratebox/config.php
  sed -i "s|<TPL:OPT_RENAMING>|${ynh_opt_renaming}|" -i /var/www/piratebox/config.php
  sed -i "s|<TPL:OPT_DELETING>|${ynh_opt_deleting}|" -i /var/www/piratebox/config.php
  sed -i "s|<TPL:OPT_CHAT>|${ynh_opt_chat}|" -i /var/www/piratebox/config.php

  cp /etc/nginx/{,conf.d/}captive-piratebox.conf

  systemctl reload nginx --quiet
}

start_fakedns() {
  (/usr/local/bin/piratebox_fakedns "${ynh_ip4_nat_prefix}.1" &> /dev/null) &
}

## Unsetters

unset_nat4_dns() {
  iptables -t nat -D PREROUTING -i "${ynh_wifi_device}" -p udp --dport 53 -j DNAT --to-destination "${ynh_ip4_nat_prefix}.1:4253"
  iptables -t nat -D POSTROUTING -o "${ynh_wifi_device}" -j MASQUERADE
}

unset_nat4_web() {
  iptables -t nat -D PREROUTING -i "${ynh_wifi_device}" -p tcp --dport 80 -j REDIRECT --to-port 4280
}

unset_filt4_nohttps() {
  iptables -D INPUT -i "${ynh_wifi_device}" -p tcp --dport 443 -j REJECT
}

unset_filt4_nofwd() {
  iptables -D FORWARD -j REJECT -i "${ynh_wifi_device}"
}

unset_captive() {
  rm -f /etc/nginx/conf.d/captive-piratebox.conf

  systemctl reload nginx --quiet
}

stop_fakedns() {
  kill $(ps aux | grep piratebox_fakedns | awk '{ print $2 }' | head -n1)
}

## Tools

moulinette_get() {
  var=${1}

  value=$(yunohost app setting piratebox "${var}")

  if [[ "${value}" =~ "An instance is already running" ]]; then
    echo "${value}" >&2
    exit 1
  fi

  echo "${value}"
}

moulinette_hotspot_get() {
  var=${1}

  value=$(yunohost app setting hotspot "${var}")

  if [[ "${value}" =~ "An instance is already running" ]]; then
    echo "${value}" >&2
    exit 1
  fi

  echo "${value}"
}

if [ "$1" != restart ]; then

  # Restart php5-fpm at the first start (it needs to be restarted after the slapd start)
  if [ ! -e /tmp/.ynh-piratebox-boot ]; then
    touch /tmp/.ynh-piratebox-boot
    systemctl restart php5-fpm --quiet
  fi
  
  # Variables
  
  echo -n "Retrieving Yunohost settings... "
  
  ynh_service_enabled=$(moulinette_get service_enabled)
  ynh_wifi_device_id=$(moulinette_get wifi_device_id)
  ynh_opt_renaming=$(moulinette_get opt_renaming)
  ynh_opt_deleting=$(moulinette_get opt_deleting)
  ynh_opt_chat=$(moulinette_get opt_chat)
  ynh_opt_name=$(moulinette_get opt_name)

  if [ "${ynh_wifi_device_id}" -eq 0 ]; then
    ynh_wifi_device="$(moulinette_hotspot_get wifi_device)"
  else
    ynh_wifi_device="hotspot${ynh_wifi_device_id}"
  fi

  IFS='|' read -a ynh_ip4_nat_prefix <<< "$(moulinette_hotspot_get ip4_nat_prefix)"
  ynh_ip4_nat_prefix=${ynh_ip4_nat_prefix[${ynh_wifi_device_id}]}
  
  echo "OK"
fi

# Script

case "$1" in
  start)
    if is_running; then
      echo "Already started"
    elif [ "${ynh_service_enabled}" -eq 0 ]; then
      echo "Disabled service"
    elif ! has_hotspot_app; then
      echo "[ERR] Hotspot is not running"
    else
      echo "[piratebox] Starting..."
      touch /tmp/.ynh-piratebox-started

      # Purge tmp folder
      rm -rf /var/spool/piratebox/*

      # Set IPv4 DNS NAT
      if ! is_nat4_dns_set; then
        echo "Set IPv4 DNS NAT"
        set_nat4_dns
      fi

      # Set IPv4 Web NAT
      if ! is_nat4_web_set; then
        echo "Set IPv4 Web NAT"
        set_nat4_web
      fi

      # Set IPv4 No Https-filter rule
      if ! is_filt4_nohttps_set; then
        echo "Set IPv4 No Https-filter rule"
        set_filt4_nohttps
      fi

      # Set IPv4 No Forwarding-filter rule
      if ! is_filt4_nofwd_set; then
        echo "Set IPv4 No Forwarding-filter rule"
        set_filt4_nofwd
      fi

      # Set captive configuration
      if ! is_captive_set; then
        echo "Set the captive portal configuration"
        set_captive
      fi

      # Run fakedns
      if ! is_fakedns_running; then
        echo "Run fakedns"
        start_fakedns
      fi
    fi
  ;;
  stop)
    echo "[piratebox] Stopping..."
    rm -f /tmp/.ynh-piratebox-started

    if is_nat4_dns_set; then
      echo "Unset IPv4 DNS NAT"
      unset_nat4_dns
    fi

    if is_nat4_web_set; then
      echo "Unset IPv4 Web NAT"
      unset_nat4_web
    fi

    if is_filt4_nohttps_set; then
      echo "Unset IPv4 No Https-filter rule"
      unset_filt4_nohttps
    fi

    if is_filt4_nofwd_set; then
      echo "Unset IPv4 No Forwarding-filter rule"
      unset_filt4_nofwd
    fi

    if is_captive_set; then
      echo "Unset the captive portal"
      unset_captive
    fi

    if is_fakedns_running; then
      echo "Stop fakedns"
      stop_fakedns
    fi

    rm -rf /var/spool/piratebox/*
  ;;
  restart)
    $0 stop
    $0 start
  ;;
  status)
    exitcode=0

    if [ "${ynh_service_enabled}" -eq 0 ]; then
      echo "[ERR] PirateBox Service disabled"
      exitcode=1
    fi

    if ! has_hotspot_app; then
      echo "[ERR] Hotspot is not running"
      exitcode=1
    fi

    if is_nat4_dns_set; then
      echo "[OK] IPv4 DNS NAT set"
    else
      echo "[ERR] No IPv4 DNS NAT set"
      exitcode=1
    fi

    if is_nat4_web_set; then
      echo "[OK] IPv4 Web NAT set"
    else
      echo "[ERR] No IPv4 Web NAT set"
      exitcode=1
    fi

    if is_filt4_nohttps_set; then
      echo "[OK] IPv4 No Https-filter rule set"
    else
      echo "[ERR] No IPv4 No Https-filter rule set"
      exitcode=1
    fi

    if is_filt4_nofwd_set; then
      echo "[OK] IPv4 No Forwarding-filter rule set"
    else
      echo "[ERR] No IPv4 No Forwarding-filter rule set"
      exitcode=1
    fi

    if is_captive_set; then
      echo "[OK] Captive portal set"
    else
      echo "[ERR] No captive portal set"
      exitcode=1
    fi

    if is_fakedns_running; then
      echo "[OK] Fakedns is running"
    else
      echo "[ERR] Fakedns is not running"
      exitcode=1
    fi

    exit ${exitcode}
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
  ;;
esac

exit 0