#!/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

ALL_24CHAN="2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472"
NOOLAP_24CHAN="2412 2437 2462"
ALL_58CHAN="5180 5200 5220 5240 5260 5280 5300 5320 5500 5520 5540 5560 5580 5600 5620 5640 5660 5680 5700"
NOOLAP_58CHAN="5180 5220 5260 5300 5500 5540 5580 5620 5660"
NOOLAP_40_58CHAN="5180 5260 5500 5580 5660"

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-0}" == "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
	for freq in ${NOOLAP_24CHAN} ${NOOLAP_40_58CHAN};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_chan(){
	freq=$(scan_freq ${1} |sort -nr |tail -1 |awk '{printf $2}')
	case ${freq} in
		2412)chan=1;;
		2417)chan=2;;
		2422)chan=3;;
		2427)chan=4;;
		2432)chan=5;;
		2437)chan=6;;
		2442)chan=7;;
		2447)chan=9;;
		2452)chan=9;;
		2457)chan=10;;
		2462)chan=11;;
		2467)chan=12;;
		2472)chan=13;;
		5180)chan=36;;
		5200)chan=40;;
		5220)chan=44;;
		5240)chan=48;;
		5260)chan=52;;
		5280)chan=56;;
		5300)chan=60;;
		5320)chan=64;;
		5500)chan=100;;
		5520)chan=104;;
		5540)chan=108;;
		5560)chan=112;;
		5580)chan=116;;
		5600)chan=120;;
		5620)chan=124;;
		5640)chan=128;;
		5660)chan=132;;
		5680)chan=136;;
		5700)chan=140;;
	esac
	echo ${chan}
}

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(){
	chan=$(get_chan ${1})
	if [ ${chan} -lt 15 ];then
		mode="g"
		width="HT20"
	else
		mode="a"
		width="HT40+"
	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;

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

	cat<<__EOF_HOSTAPD__
interface=${1}
hw_mode=${mode}
country_code=ZA
ieee80211h=1
ieee80211d=1
ieee80211n=1
ht_capab=[${width}]${HT_CAPAB}
ieee80211ac=1
wmm_enabled=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;

	if [ "${WIFI_MODE}" == "STA" ];then
		config_ipv6_rt ${IPV6-0} ${IFACE_STA}
		config_ipv6_rt 0 ${IFACE_AP}
		IFACE_ACT=${IFACE_STA}
	else
		config_ipv6_rt ${IPV6-0} ${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
