#!/bin/sh

# Source function library
. /etc/init.d/functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DESC=WiFi

IFACE_STA=wlan0
DAEMON_STA=/usr/sbin/wpa_supplicant
PIDFILE_STA=/var/run/wpa_supplicant/${IFACE_STA}.pid

IFACE_AP=wlan1
DAEMON_AP=/usr/sbin/hostapd
PIDFILE_AP=/var/run/hostapd.${IFACE_AP}.pid

DAEMON_DHCP=/sbin/udhcpc
PIDFILE_DHCP=/var/run/udhcpc.${IFACE_STA}.pid

NOOLAP_20_24CHAN="2412 2432 2452 2472"
NOOLAP_25_24CHAN="2412 2437 2462"
NOOLAP_40_H_24CHAN="2412 2452"
NOOLAP_40_L_24CHAN="2432 2472"

NOOLAP_20_5CHAN="5180 5200 5220 5240"
NOOLAP_40_H_5CHAN="5180 5220"
NOOLAP_40_L_5CHAN="5200 5240"

I2C=$(ls -d  /sys/bus/i2c/drivers/nau8810/*1a |cut -d/ -f7 |cut -d- -f1)
ARCH_FAMILY=$(cut -d- -f1 /etc/rpm/platform |tr '_' '-'|cut -d- -f1)

if [ "${ARCH_FAMILY}" == "raspberrypi" ];then
	SERPRE=0010;
 elif [ "${ARCH_FAMILY:0:10}" == "stm32mp157" ];then
	SERPRE=0012;
fi

if [ -e /etc/default/wifi ];then
	source /etc/default/wifi
fi;

set -e

config_ipv6_rt() {
	if [ ! -d /proc/sys/net/ipv6/conf/${2} ];then
		return 0
	fi;

	if [ "${1}" == "1" ];then
		echo 1 >/proc/sys/net/ipv6/conf/${2}/forwarding
		if [ "${IPV6RA-1}" == "1" ];then
			echo 2 >/proc/sys/net/ipv6/conf/${2}/accept_ra
			echo 1 >/proc/sys/net/ipv6/conf/${2}/accept_redirects
		else
			echo 1 >/proc/sys/net/ipv6/conf/${2}/accept_ra
			echo 0 >/proc/sys/net/ipv6/conf/${2}/accept_redirects
		fi
	else
		echo 0 >/proc/sys/net/ipv6/conf/${2}/forwarding
		echo 1 >/proc/sys/net/ipv6/conf/${2}/accept_ra
		echo 1 >/proc/sys/net/ipv6/conf/${2}/accept_redirects
	fi
	echo 1 >/proc/sys/net/ipv6/conf/${2}/accept_ra_defrtr
	echo 0 >/proc/sys/net/ipv6/conf/${2}/accept_ra_from_local
	echo 2 >/proc/sys/net/ipv6/conf/${2}/use_tempaddr
}

scan_freq(){
	/usr/sbin/iw ${1} scan |grep -Po '(signal|freq):\K.*' | paste -d ' ' - - > /tmp/wifi.scan

	case ${2} in
		2.4G)if [ "x${WIDTH}" == "x40+" ];then
			CLIST=${NOOLAP_40_H_24CHAN};
		     elif [ "x${WIDTH}" == "x40-" ];then
			CLIST=${NOOLAP_40_L_24CHAN};
		     elif [ "x${WIDTH}" == "x25" ];then
			CLIST=${NOOLAP_25_24CHAN};
		     else
			CLIST=${NOOLAP_20_24CHAN}
		     fi;;
		5G)if [ "x${WIDTH}" == "x20" ];then
			CLIST=${NOOLAP_20_5CHAN};
		   elif [ "x${WIDTH}" == "x40-" ];then
			CLIST=${NOOLAP_40_L_5CHAN};
		   else
			CLIST=${NOOLAP_40_H_5CHAN};
		   fi;;
		*)CLIST="${NOOLAP_20_24CHAN} ${NOOLAP_40_H_5CHAN}";;
	esac;

	for freq in ${CLIST};do
		(echo "-99.99 ${freq}";
		awk -v freq=${freq} '$1 == freq {printf "%s %s\n",$2,$1}' /tmp/wifi.scan) |sort -n |tail -1
	done;
	rm /tmp/wifi.scan
}

get_i2c() {
	if i2cdetect -a -r -y ${I2C} 0x${1} 0x${1} |tail -8 |cut -c5- |grep ${1} > /dev/null 2>&1;then
		return 0;
	else
		return 1;
	fi;
}

get_i2c_reg() {
	if i2cdetect -a -r -y ${I2C} 0x${1} 0x${1} |tail -8 |cut -c5- |grep UU > /dev/null;then
		return 0;
	else
		return 1;
	fi;
}

hostapd_conf(){
	case ${BAND} in
		""|"2.4G"|"5G")
			freq=$(scan_freq ${1} ${BAND}|sort -nr |tail -1 |awk '{printf $2}')
		;;
		*)
			freq=${BAND}
		;;
	esac
	if [ ${freq} -lt 5000 ];then
		chan=$(((${freq}-2407)/5))
	else
		chan=$(((${freq}-5000)/5))
	fi
	if [ ${chan} -lt 15 ];then
		mode="g"
		if [ -z ${WIDTH} ];then
			width="[HT20]"
		else
			width="[HT${WIDTH}]"
		fi;
	else
		mode="a"
		if [ -z ${WIDTH} ];then
			width="[HT40+][SHORT-GI-40]"
		elif [ "x${WIDTH}" == "x20" ];then
			width="[HT20]"
		else
			width="[HT${WIDTH}][SHORT-GI-40]"
		fi;
	fi;

	if [ ! "${SSID}" ] && [ "${WIFI_MODE}" == "DEF" ];then
		SSID=$(awk -F: '{printf "comb-ns-%s%s%s%s",$3,$4,$5,$6}' /sys/class/net/${1}/address)


		if get_i2c 50;then
			PPHRASE=$(echo -n ${SERPRE};for mac in a b c d e f;do MV=$(i2cget -y ${I2C} 0x50 0xf${mac});echo -n ${MV:2};done)
		 elif get_i2c 57;then
			PPHRASE=$(echo -n ${SERPRE};for mac in a b c d e f;do MV=$(i2cget -y ${I2C} 0x57 0xf${mac});echo -n ${MV:2};done)
		 elif get_i2c_reg 50;then
			eeprom_dev=$(printf "/sys/bus/i2c/devices/%d-%04X/eeprom" ${I2C} 0x50)
			PPHRASE=$(echo -n ${SERPRE};hexdump -C -n 6 --skip 0xFA ${eeprom_dev} |cut -c11-27 |sed -e 's/ //g')
		else
			PPHRASE="password"
		fi;


		PSK=$(wpa_passphrase "${SSID}" ${PPHRASE} |awk -F= '/\tpsk=/ {printf "%s\n",$2}')
		/usr/bin/avahi-set-host-name "${SSID}" |true
		/bin/hostname "${SSID}"
	elif [ ! "${SSID}" ];then
		return 1;
	fi;

	HT_CAPAB="[SHORT-GI-20][MAX-AMSDU-3839]"

	if [ -e /etc/rpm/platform ];then
		NS_PLAT=$(cut -d- -f1 /etc/rpm/platform |tr '_' '-')
		case ${NS_PLAT} in
			raspberrypi-cm4-64)
				if [ "${mode}" == "g" ];then
					HT_CAPAB="${HT_CAPAB}[SHORT-GI-40]"
				fi;
			;;
			stm32mp157c-ns-combo | stm32mp157f-ns-combo)
			;;
		esac;
	fi;

	if [ "${mode}" == "g" ];then
		HT_CAPAB="${HT_CAPAB}[DSSS_CCK-40]"
	fi;

	cat<<__EOF_HOSTAPD__
interface=${1}
hw_mode=${mode}
country_code=ZA
ieee80211h=1
ieee80211d=1
ieee80211n=1
ctrl_interface=/run/hostapd
ht_capab=${width}${HT_CAPAB}
ieee80211ac=1
wmm_enabled=1
#local_pwr_constraint=3
#spectrum_mgmt_required=1
channel=${chan}

auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=TKIP CCMP

wpa_psk=${PSK}
ssid=${SSID}
__EOF_HOSTAPD__
}


supplicant_config() {
  cat<<__EOF__
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
country=ZA

network={
	ssid="${1}"
        psk=${2}
}
__EOF__
}


setup_ap() {
	if [ ! "${1}" ] || [ "${WIFI_MODE}" == "DEF" ];then
		/sbin/ip link set nomaster dev ${IFACE_AP}
		/sbin/ip addr flush dev ${IFACE_AP} scope global
		/sbin/ip addr add ${IP}/${SN} dev ${IFACE_AP}
	elif [ ! -d /sys/class/net/${1}/brif/${IFACE_AP} ];then
		/sbin/ip addr flush dev ${IFACE_AP} scope global
		/sbin/ip link set dev ${IFACE_AP} master ${1}
	fi
}


setul_ula_addr() {
	if [ ! "${2}" ];then
		return
	fi

	if [ -e /etc/default/static ];then
		source /etc/default/static
	else
		return
	fi

	if [[ "${2}" =~ .*":".* ]]; then
		if [  "${2:0:1}" == ":"	];then
			/sbin/ip addr add ${IPV6ULA}${2}/64 dev ${1} | :
		else
			/sbin/ip addr add ${IPV6ULA}:${2}/64 dev ${1} | :
		fi
	fi
}

case $1 in
  start)
	echo -n "Starting ${DESC}: "
	if [ -d /sys/module/brcmfmac ] && [ ! -d /sys/class/net/wlan0 ];then
		rmmod brcmfmac
		modprobe brcmfmac
		sleep 1
	fi
	if [ ! -e /sys/class/net/${IFACE_STA} ];then
		echo  "No WiFi support"
		exit 0
	fi;

	/usr/sbin/iw reg set ZA

	if [ "${WIFI_MODE}" == "STA" ];then
		config_ipv6_rt ${IPV6-1} ${IFACE_STA}
		config_ipv6_rt 0 ${IFACE_AP}
		IFACE_ACT=${IFACE_STA}
	else
		config_ipv6_rt ${IPV6-1} ${IFACE_AP}
		config_ipv6_rt 0 ${IFACE_STA}
		IFACE_ACT=${IFACE_AP}
	fi
	echo 2048 >/proc/sys/net/ipv6/conf/${IFACE_ACT}/ra_defrtr_metric |:

	if [ -e /etc/wpa_supplicant.conf ] && [ "${WIFI_MODE}" == "STA" ];then
		/sbin/ip link set dev ${IFACE_AP} down
		/sbin/ip link set dev ${IFACE_STA} up
		start-stop-daemon --start -p ${PIDFILE_STA} ${DAEMON_STA} -- -B -P ${PIDFILE_STA} -D nl80211 -i ${IFACE_STA}  -c /etc/wpa_supplicant.conf
		if [ "${DHCP-1}" == "1" ];then
			start-stop-daemon --start -p ${PIDFILE_DHCP} ${DAEMON_DHCP} -- -R -b -p ${PIDFILE_DHCP} -i ${IFACE_STA}
		else
			interface=${IFACE_STA} /etc/udhcpc.d/90comb-static renew | :
			interface=${IFACE_STA} /etc/udhcpc.d/99kernel-pnp renew | :
		fi;
	elif [ ! -e /etc/wpa_supplicant.conf ] && [ "${WIFI_MODE}" == "STA" ] &&  [ "${SSID}" ] &&  [ "${PSK}" ];then
		/sbin/ip link set dev ${IFACE_AP} down
		/sbin/ip link set dev ${IFACE_STA} up
		supplicant_config "${SSID}" ${PSK} > /tmp/wpa_supplicant.conf
		start-stop-daemon --start -p ${PIDFILE_STA} ${DAEMON_STA} -- -B -P ${PIDFILE_STA} -D nl80211 -i ${IFACE_STA}  -c /tmp/wpa_supplicant.conf
		if [ "${DHCP-1}" == "1" ];then
			start-stop-daemon --start -p ${PIDFILE_DHCP} ${DAEMON_DHCP} -- -R -b -p ${PIDFILE_DHCP} -i ${IFACE_STA}
		else
			interface=${IFACE_STA} /etc/udhcpc.d/90comb-static renew | :
			interface=${IFACE_STA} /etc/udhcpc.d/99kernel-pnp renew | :
		fi;
	elif [ -e /etc/hostapd.conf ] && [ "${WIFI_MODE}" != "OFF" ];then
		/sbin/ip link set dev ${IFACE_STA} down
		/sbin/ip link set dev ${IFACE_AP} up
		setup_ap ${WIFI_AP_BRIDGE}
		start-stop-daemon --start -p ${PIDFILE_AP} ${DAEMON_AP} -- -P ${PIDFILE_AP} -B /etc/hostapd.conf
		/sbin/ip route add 169.254.0.0/16 dev ${IFACE_AP} scope link metric 1100
	elif [ ! -e /etc/hostapd.conf ] && [ "${WIFI_MODE}" ] && [ "${WIFI_MODE}" != "OFF" ];then
		setup_ap ${WIFI_AP_BRIDGE}
		/sbin/ip link set dev ${IFACE_STA} down
		/sbin/ip link set dev ${IFACE_AP} up
		hostapd_conf ${IFACE_AP} ${SSID} ${PSK} > /tmp/hostapd.conf
		start-stop-daemon --start -p ${PIDFILE_AP} ${DAEMON_AP} -- -P ${PIDFILE_AP} -B /tmp/hostapd.conf
		/sbin/ip route add 169.254.0.0/16 dev ${IFACE_AP} scope link metric 1100
	fi;

	/sbin/ip -6 addr flush scope global dev ${IFACE_ACT}
	for ipaddr in ${IPV6ADDR};do
		/sbin/ip addr add ${ipaddr} dev ${IFACE_ACT} | :
	done
	setul_ula_addr ${IFACE_ACT} ${IPV6ULANET}
  ;;
  stop)
	echo -n "Stopping {$DESC}: "
	if [ -e ${PIDFILE_STA} ];then
		/sbin/ip addr flush dev ${IFACE_STA} scope global
		/sbin/ip -6 addr flush scope global dev ${IFACE_STA}
		start-stop-daemon --stop -p ${PIDFILE_STA} ${DAEMON_STA} || true
		config_ipv6_rt 0 ${IFACE_STA}
		/sbin/ip link set dev ${IFACE_STA} down
		if [ -e ${PIDFILE_STA} ];then
			rm ${PIDFILE_STA}
		fi;
	fi;
	if [ -e ${PIDFILE_AP} ];then
		/sbin/ip addr flush dev ${IFACE_AP} scope global
		/sbin/ip -6 addr flush scope global dev ${IFACE_AP}
		start-stop-daemon --stop -s SIGKILL -p ${PIDFILE_AP} ${DAEMON_AP} || true
		config_ipv6_rt 0 ${IFACE_AP}
		/sbin/ip link set dev ${IFACE_AP} down
		if [ -e ${PIDFILE_AP} ];then
			rm ${PIDFILE_AP}
		fi;
	fi;
	if [ -e ${PIDFILE_DHCP} ];then
		start-stop-daemon --stop -s SIGKILL -p ${PIDFILE_DHCP} ${DAEMON_DHCP} || true
		if [ -e ${PIDFILE_DHCP} ];then
			rm ${PIDFILE_DHCP}
		fi;
	fi;
  ;;
  restart|force-reload)
	$0 stop
	sleep 1
	$0 start
  ;;
  status)
	status ${DAEMON} || exit $?
  ;;
  *)
	N=/etc/init.d/wifi
	echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
	exit 1
	;;
esac

exit 0
