#!/bin/sh
#
# Konfiguriere uebliche Opennet-Interfaces sowie ein lokales Interface.
#
# Dieses Skript wird nur ein einziges Mal nach einem Upgrade oder der Erstinstallation ausgefuehrt:
#   http://wiki.openwrt.org/doc/uci#defaults
#


# shellcheck source=opennet/packages/on-core/files/usr/lib/opennet/on-helper.sh
. "${IPKG_INSTROOT:-}/usr/lib/opennet/on-helper.sh"


OPENWRT_DEFAULT_LOCAL_IP=192.168.1.1


configure_local_network() {
	local uci_prefix="network.$NETWORK_LOCAL"
	# wurde die Standard-IP bereits veraendert?
	[ "$(uci_get "${uci_prefix}.ipaddr")" !=  "$OPENWRT_DEFAULT_LOCAL_IP" ] && return 0
	uci set "${uci_prefix}.ipaddr=$(get_on_core_default lan_ipaddr)"
	uci set "${uci_prefix}.netmask=$(get_on_core_default lan_netmask)"
}


configure_opennet_zone() {
	local uci_prefix
	# Forwarding (die letzte Aktion dieses Ablaufs) existiert? Keine Aenderungen ...
	[ -n "$(find_first_uci_section "firewall" "forwarding" "src=$ZONE_MESH" "dest=$ZONE_MESH")" ] && return 0
	uci_prefix=$(find_first_uci_section "firewall" "zone" "name=$ZONE_MESH")
	# Zone anlegen, falls leer
	[ -z "$uci_prefix" ] && uci_prefix=firewall.$(uci add firewall zone)
	uci set "$uci_prefix=zone"
	uci set "$uci_prefix.name=$ZONE_MESH"
	# Opennet-APs bieten ueblicherweise keine privaten Dienste an
	uci set "$uci_prefix.input=ACCEPT"
	# ausgehende Pakete sind OK
	uci set "$uci_prefix.output=ACCEPT"
	# Verkehr aus dem opennet-Netz darf nicht in lokale oder tunnel-Netze
	uci set "$uci_prefix.forward=REJECT"
	# via "masq_src" ersetzen wir die ehemalige "/etc/firewall.opennet" fuer Quell-basiertes Masquerading
	add_zone_forward "$ZONE_LOCAL" "$ZONE_MESH"
	# intra-Zone-Verkehr muss explizit erlaubt werden
	add_zone_forward "$ZONE_MESH" "$ZONE_MESH"
}


configure_olsr_radio() {
	trap 'error_trap configure_olsr_radio "$*"' EXIT
	local iface_index="$1"
	local iface_logical="$2"
	local iface_device="$3"

	local uci_wifi="wireless.@wifi-iface[$iface_index]"
	local uci_radio
	local radio_band
	local bssid
	uci_radio="wireless.$(uci_get "${uci_wifi}.device")"
	radio_band=$(uci_get "${uci_radio}.band")
	htmode=$(uci_get "${uci_radio}.htmode")
	bssid=$(get_on_core_default wifi_bssid)

	uci set "${uci_wifi}.network=$iface_logical"
	uci set "${uci_wifi}.device=$iface_device"

	uci set "wireless.radio${iface_index}.country=$(get_on_core_default wifi_country)"
	uci_delete "wireless.radio${iface_index}.disabled"

	# typ-spezifische Attribute
	if echo "$radio_band" | grep -q "5g"; then
		# 5 GHz: kein Mesh-Modus verfuegbar
		uci set "${uci_wifi}.ssid=$(get_on_core_default wifi_ssid_5ghz)"
		uci set "${uci_wifi}.mode=$(get_on_core_default wifi_mode_5ghz)"
		# Use one (random) indoor channel and multiple outdoor channels. 
		# Indoor channel: as fallback otherwise wireless scans fail (ap + DFS channel -> no scan)
		# Outdoor channels: remove TDWR channels + bandwidth
		indoor_channel=$(( 36 + 4 * $(get_random 4) ))
		uci set "${uci_radio}.channel=$indoor_channel"
		uci set "${uci_radio}.chanlist=$indoor_channel $(get_on_core_default wifi_outdoor_chanlist_5ghz)"
		# Fix 11ac default bandwidth
		if [ "$htmode" = "VHT80" ]; then
			uci set "${uci_radio}.htmode=VHT20"
		fi
		uci set "${uci_wifi}.isolate=1"
		# wir wollen einfache Interface Namen haben (wlan0,wlan1) und keine kryptischen Namen (phy-ap0,phy-sta0,...)
		uci set "${uci_wifi}.ifname=wlan${iface_index}"
	else
		# 2,4 GHz: Ad-hoc-Modus
		uci set "${uci_wifi}.ssid=$(get_on_core_default wifi_ssid)"
		uci set "${uci_wifi}.mode=$(get_on_core_default wifi_mode)"
		[ -n "$bssid" ] && uci set "${uci_wifi}.bssid=$bssid"
		uci set "${uci_radio}.channel=$(get_on_core_default wifi_channel)"
		# wir wollen einfache Interface Namen haben (wlan0,wlan1) und keine kryptischen Namen (phy-ap0,phy-sta0,...)
		uci set "${uci_wifi}.ifname=wlan${iface_index}"
	fi
	return
}


configure_olsr_single_interface() {
	trap 'error_trap configure_olsr_single_interface "$*"' EXIT
	local iface_logical="$1"
	local iface_addr="$2"
	local iface_netmask="$3"
	local iface_device="$4"

	# configure on_wifi
	uci set "network.${iface_logical}=interface"
	uci set "network.${iface_logical}.proto=static"
	uci set "network.${iface_logical}.netmask=$iface_netmask"
	uci set "network.${iface_logical}.defaultroute=0"
	uci set "network.${iface_logical}.peerdns=0"
	uci set "network.${iface_logical}.ipaddr=$iface_addr"

	# disable dhcp on on_wifi
	uci set "dhcp.${iface_logical}=dhcp"
	uci set "dhcp.${iface_logical}.interface=${iface_logical}"
	uci set "dhcp.${iface_logical}.dynamicdhcp=0"
	uci set "dhcp.${iface_logical}.ignore=1"
}


configure_olsr_interfaces() {
	trap 'error_trap configure_olsr_interfaces "$*"' EXIT

	# diese Aktion ist bereits abgeschlossen
	uci -q show "network" | grep -q '^network\.on_eth_0\.' && return 0

	local on_id
	local on_ipschema
	local on_netmask
	on_id=$(uci_get on-core.settings.on_id "$(get_on_core_default on_id_preset)")
	on_ipschema=$(get_on_core_default on_ipschema)
	on_netmask=$(get_on_core_default on_netmask)
	local on_ipaddr
	local iface_phys
	local iface_logical

	# Erstelle wifi config in uci, falls noch keine vorhanden ist
	/sbin/wifi config

	local iface_index=0
	while [ -n "$(uci_get "wireless.@wifi-iface[${iface_index}]")" ]; do
		on_ipaddr=$(get_on_ip "$on_id" "$on_ipschema" "$iface_index")
		iface_wifi_device=$(uci_get "wireless.@wifi-iface[${iface_index}].device")
		iface_logical=on_wifi_$iface_index

		configure_olsr_single_interface "$iface_logical" "$on_ipaddr" "$on_netmask" "$iface_wifi_device"
		configure_olsr_radio "$iface_index" "$iface_logical" "$iface_wifi_device"

		add_interface_to_zone "$ZONE_MESH" "$iface_logical"

		iface_index=$((iface_index + 1))
	done

	for iface_logical in "on_eth_0" "on_eth_1"; do
		on_ipaddr=$(get_on_ip "$on_id" "$on_ipschema" "$iface_index")
		iface_phys=none
		configure_olsr_single_interface "$iface_logical" "$on_ipaddr" "$on_netmask" "$iface_phys"
		add_interface_to_zone "$ZONE_MESH" "$iface_logical"
		iface_index=$((iface_index + 1))
	done
}


# jede Funktion sollte selbst pruefen, ob ihre Aktion bereits abgeschlossen ist
configure_local_network
configure_opennet_zone
configure_olsr_interfaces

apply_changes network wireless dhcp firewall
