#!/bin/bash

# This file is part of TorBox, an easy to use anonymizing router based on Raspberry Pi.
# Copyright (C) 2026 radio_24
# Contact: anonym@torbox.ch
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 is useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# DESCRIPTION
# This file tries to fix all network-related problems, like wrong assigned IP
# addresses, issues with dhclient, hostapd, and others. It also restarts
# TorBox's wireless network (AP, hostapd) if we use a WLAN adapter as an AP,
# checks if the daemon is working, and, if not, resets the configuration with
# the last working version and restarts the daemon again. If nothing works,
# the configuration is set that way that after a restart, TorBox's wireless
# network can be found on wlan0.
#
# SYNTAX
# nohup ./hostapd_fallback_komplex_new <interface 1> <interface 2> <notusb0>
#
# <interface 1>: Is the interface with the AP: wlan0 or wlan1.
# <interface 2>: Is the interface with the connected cable client: eth0 or eth1
# <notusb0>: If set, there is no usb0-client present
#
# IMPORTANT
# There is no failsave configuration in this procedure, because it interfered
# with the rest. The failsave is part of the rc.local script. It will check for
# wlan1 entries in the configuration fails and substitutet them with wlan0.
#
#
RUNFILE="/home/torbox/torbox/run/torbox.run"
ON_A_CLOUD=$(grep "^ON_A_CLOUD=.*" ${RUNFILE} | sed "s/.*=//g")
TORBOX_MINI=$(grep "^TORBOX_MINI=.*" ${RUNFILE} | sed "s/.*=//g")

##### SET VARIABLES ######

#Other variables
HOSTAPD="/etc/hostapd/hostapd.conf"
INTERFACE1=$1
INTERFACE2=$2
NOTUSB0=$3
INTERFACE1_DOWN=0
INTERFACE2_DOWN=0
INTERFACE3_DOWN=0
INTERFACE_USB0_DOWN=0

# Check for active SSH connections on USB0 before restarting
USB0_SSH_ACTIVE=0
if ss -tn | grep -q ":22.*192\.168\.44\." ; then
	USB0_SSH_ACTIVE=1
fi

# INTERFACE1 and INTERFACE2 are clients - INTERFACE3 and INTERFACE4 are potential Internet sources
if [ "$INTERFACE1" == "wlan1" ] ; then
	INTERFACE3="wlan0"
else
	INTERFACE3="wlan1"
fi

if [ "$INTERFACE2" == "eth1" ] ; then
	INTERFACE4="eth0"
else
	INTERFACE4="eth1"
fi

# First, we have to shutdown the interface with running dhcpclients, before we copy the interfaces file
# pgrep -f "dhclient.$INTERFACE1" will only return true, if the Internet is on INTERFACE1
# no need to change anything if INTERFACE1 was already the AP
#
# We have also to take down the Interface with the old AP to avoid that the IP address (192.168.4x.1) is given twice
# ATTENTION: If this will disconnect the clients or hang TorBox then dhclient has to be removed.
# ATTENTION: Under Raspberry Pi OS we can grep dhclient, but under Debian that's not possible because dclient is started on
#            all interfaces. We have to avoid to take down the interface with the AP!

if pgrep -f "dhclient.$INTERFACE1" ; then
	(sudo dhclient -r) 2>&1
	# We can only do that, if the interface is not used as AP
	if ! grep "^interface=$INTERFACE1" ${HOSTAPD} ; then
		sudo ifdown $INTERFACE1 &>/dev/null
		INTERFACE1_DOWN=1
	fi
	if ! grep "^interface=$INTERFACE3" ${HOSTAPD} ; then
		sudo ifdown $INTERFACE3 &>/dev/null
		INTERFACE3_DOWN=1
	fi
fi

if pgrep -f "dhclient.$INTERFACE2" ; then
	(sudo dhclient -r) 2>&1
	sudo ifdown $INTERFACE2 &>/dev/null
	# NEW v.0.5.4-post: This will disconnect a cable connection
	# sudo ifdown $INTERFACE4
	INTERFACE2_DOWN=1
fi

if [ "$TORBOX_MINI" -eq "1" ]; then
	NOTUSB0=""
	if pgrep -f "dhclient.usb0" && [ "$USB0_SSH_ACTIVE" -eq "0" ] ; then
		(sudo dhclient -r) 2>&1
		sudo ifdown usb0 &>/dev/null
		# NEW v.0.5.4-post: This will disconnect a cable connection
		# sudo ifdown $INTERFACE4
		INTERFACE_USB0_DOWN=1
	fi
fi

if [ "$ON_A_CLOUD" -eq "0" ]; then
	sudo cp /etc/network/interfaces /etc/network/interfaces.bak
	sudo cp etc/network/interfaces.$INTERFACE1$INTERFACE2$NOTUSB0 /etc/network/interfaces
fi

if [ $INTERFACE1_DOWN = 1 ] ; then
		sudo ifup $INTERFACE1 &>/dev/null
		INTERFACE1_DOWN=0
fi

if [ $INTERFACE2_DOWN = 1 ] ; then
		sudo ifup $INTERFACE2 &>/dev/null
		# sudo ifup $INTERFACE4
		INTERFACE2_DOWN=0
fi

if [ $INTERFACE3_DOWN = 1 ] ; then
		sudo ifup $INTERFACE3 &>/dev/null
		INTERFACE3_DOWN=0
fi

if [ $INTERFACE_USB0_DOWN = 1 ] ; then
		sudo ifup usb0 &>/dev/null
		INTERFACE_USB0_DOWN=0
fi

# Is INTERFACE1 ready?
if ip link | grep $INTERFACE1 | grep "state UP"; then
	STATICIP1=$(ip addr show $INTERFACE1 | grep -w inet)
	# If wlan0 or wlan1 doesn't have an IP address then we have to do something about it!
	if [ -z "$STATICIP1" ] ; then
		sudo ifdown $INTERFACE1 &>/dev/null
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE1 &>/dev/null
	fi
	unset STATICIP1
	# Avoiding to have no IP
	STATICIP1=$(ip addr show $INTERFACE1 | grep 192.168.42.1)
	if [ -z "$STATICIP1" ] ; then
		sudo ifdown $INTERFACE1 &>/dev/null
		ip addr flush dev $INTERFACE1
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE1 &>/dev/null
	fi
else
		sudo ifdown $INTERFACE1 &>/dev/null
		ip addr flush dev $INTERFACE1
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE1 &>/dev/null
fi

# Is INTERFACE2 ready?
# Only executed if the interface is down and not used for a cable client
if ip link | grep $INTERFACE2 | grep "state UP" ; then
	STATICIP2=$(ip addr show $INTERFACE2 | grep -w 192.168.43.1)
	if [ -z "$STATICIP2" ] ; then
		sudo ifdown $INTERFACE2 &>/dev/null
		ip addr flush dev $INTERFACE2
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE2 &>/dev/null
	fi
else
		sudo ifdown $INTERFACE2 &>/dev/null
		ip addr flush dev $INTERFACE2
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE2 &>/dev/null
fi

# If wlan0 or wlan1 is not acting as AP then we have to do something about it!
# On a cloud, with TorBox mini and when WLAN is disabled, hostapd is masked by default
AP_STATUS=$(sudo systemctl is-enabled hostapd)
if [ "$AP_STATUS" != "masked" ] ; then
	if ! grep "^interface=$INTERFACE1" ${HOSTAPD} ; then
		sudo sed -i "s/^interface=.*/interface=$INTERFACE1/" ${HOSTAPD}
		sudo systemctl restart hostapd
		sleep 5
	fi
	AP_STATUS=$(sudo systemctl is-active hostapd)
	if [ $AP_STATUS = activating ] || [ $AP_STATUS = inactive ] ; then
		sudo sed -i "s/^hw_mode=a/hw_mode=g/" ${HOSTAPD}
		sudo sed -i "s/^channel=.*/channel=6/" ${HOSTAPD}
		sudo sed -i "s/^ht_capab=[HT40-][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]/#ht_capab=[HT40-][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]/" ${HOSTAPD}
		sudo sed -i "s/^vht_oper_chwidth=1/#vht_oper_chwidth=1/" ${HOSTAPD}
		sudo sed -i "s/^vht_oper_centr_freq_seg0_idx=42/#vht_oper_centr_freq_seg0_idx=42/" ${HOSTAPD}
		sudo systemctl restart hostapd
		sleep 5
	fi
fi

# Is USB0 ready (only used in TorBox mini)?
if [ "$TORBOX_MINI" -eq "1" ]; then
	if ip link | grep usb0 | grep "state UP" ; then
		STATICIP_USB0=$(ip addr show usb0 | grep -w inet)
		# If usb0 doesn't have an IP address then we have to do something about it!
		if [ -z "$STATICIP_USB0" ]; then
			sudo ifdown usb0 &>/dev/null
			# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
			sudo ifup usb0 &>/dev/null
		fi
		unset STATICIP_USB0
		# Avoiding to have no IP
		STATICIP_USB0=$(ip addr show usb0 | grep 192.168.44.1)
		if [ -z "$STATICIP_USB0" ]; then
			sudo ifdown usb0 &>/dev/null
			ip addr flush dev usb0
			# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
			sudo ifup usb0 &>/dev/null
		fi
	else
		if [ "$USB0_SSH_ACTIVE" -eq "0" ] ; then
			sudo ifdown usb0 &>/dev/null
			ip addr flush dev usb0
			# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
			sudo ifup usb0 &>/dev/null
		fi
	fi
fi

# Is INTERFACE3 ready?
# Because it is a possible Internet source, the Interface should be up, but
# the IP adress shouldn't be 192.168.42.1 or 192.168.43.1
if ip link | grep $INTERFACE3 | grep "state UP" ; then
	STATICIP3=$(ip addr show $INTERFACE3 | grep -w inet)
	if [ -z "$STATICIP3" ] ; then
		sudo ifdown $INTERFACE3 &>/dev/null
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE3 &>/dev/null
	fi
	unset STATICIP3
	STATICIP3=$(ip addr show $INTERFACE3 | grep 192.168.42.1)
	if [ -n "$STATICIP3" ] ; then
		sudo ifdown $INTERFACE3 &>/dev/null
		ip addr flush dev $INTERFACE3 &>/dev/null
		sudo ifup $INTERFACE3 &>/dev/null &
	fi
else
		sudo ifdown $INTERFACE3 &>/dev/null
		ip addr flush dev $INTERFACE3
		sudo ifup $INTERFACE3 &>/dev/null &
fi

# Is INTERFACE4 ready?
# Because it is a possible Internet source, the Interface should be up, but
# the IP adress shouldn't be 192.168.42.1 or 192.168.43.1
if ip link | grep $INTERFACE4 | grep "state UP" ; then
	STATICIP4=$(ip addr show $INTERFACE4 | grep -w inet)
	if [ -z "$STATICIP4" ] ; then
		sudo ifdown $INTERFACE4 &>/dev/null
		# Cannot be run in the background because then it jumps into the next if-then-else clause (still missing IP)
		sudo ifup $INTERFACE4 &>/dev/null
	fi
	unset STATICIP4
	STATICIP4=$(ip addr show $INTERFACE4 | grep 192.168.43.1)
	if [ -n "$STATICIP4" ] ; then
		sudo ifdown $INTERFACE4
		ip addr flush dev $INTERFACE4
		sudo ifup $INTERFACE4 &>/dev/null &
	fi
else
		sudo ifdown $INTERFACE4
		ip addr flush dev $INTERFACE4
		sudo ifup $INTERFACE4 &>/dev/null &
fi

# This last part resets the dhcp server, which has to be used after an ifup command
# Important: the right iptables rules to use Tor have to configured afterward
if [ "$ON_A_CLOUD" -eq "0" ]; then sudo systemctl restart isc-dhcp-server; fi
# CHANGE v.0.5.5-post: I don't think this line are necessary
# sudo /sbin/iptables-restore < /etc/iptables.ipv4.nat
