#!/bin/sh

. /lib/functions.sh

convert_to_hex() {
	local val=""
	local optval="${1}"
	OPTIND=1
	while getopts ":" opt "-$optval"
	do
		temp=$(printf "%02X" "'${OPTARG:-:}")
		val="${val}:${temp}"
	done

	echo "${val}"
}

configure_send_op125() {
	local sendopt="${1}"
	local intf="${2}"
	local uci="${3}"
	local hex_oui=""
	local hex_serial=""
	local hex_class=""
	local oui_len=0
	local serial_len=0
	local class_len=0

	if [ "${uci}" = "network" ]; then
		local opt125="125:00:00:0D:E9"
	else
		if [ -z "${sendopt}" ]; then
			local opt125="125,00:00:0D:E9"
		else
			local opt125=":00:00:0D:E9"
		fi
	fi

	config_get oui cpe manufacturer_oui ""
	if [ -z "${oui}" ]; then
		oui=$(db -q get device.deviceinfo.ManufacturerOUI)
	fi

	oui=$(echo "${oui}" | tr 'a-f' 'A-F')

	config_get serial cpe serial_number ""
	if [ -z "${serial}" ]; then
		serial=$(db -q get device.deviceinfo.SerialNumber)
	fi

	config_get class cpe product_class ""
	if [ -z "${class}" ]; then
		class=$(db -q get device.deviceinfo.ProductClass)
	fi

	oui_len=$(echo -n "${oui}" | wc -m)
	serial_len=$(echo -n "${serial}" | wc -m)
	class_len=$(echo -n "${class}" | wc -m)

	if [ "${oui_len}" -eq 0 ] || [ "${serial_len}" -eq 0 ]; then
		return 0
	fi

	opt125_len=$((oui_len + serial_len + class_len))
	if [ "${class_len}" -gt 0 ]; then
		opt125_len=$((opt125_len + 6))
	else
		opt125_len=$((opt125_len + 4))
	fi

	hex_opt125_len=$(printf "%02X" "${opt125_len}")
	opt125="${opt125}:${hex_opt125_len}"
	hex_oui=$(convert_to_hex "${oui}")
	if [ -z "${hex_oui}" ]; then
		return 0
	fi

	hex_oui_len=$(printf "%02X" "${oui_len}")
	if [ "${uci}" = "network" ]; then
		opt125="${opt125}:01:${hex_oui_len}${hex_oui}"
	else
		opt125="${opt125}:04:${hex_oui_len}${hex_oui}"
	fi

	hex_serial=$(convert_to_hex "${serial}")
	if [ -z "${hex_serial}" ]; then
		return 0
	fi

	hex_serial_len=$(printf "%02X" "${serial_len}")
	if [ "${uci}" = "network" ]; then
		opt125="${opt125}:02:${hex_serial_len}${hex_serial}"
	else
		opt125="${opt125}:05:${hex_serial_len}${hex_serial}"
	fi

	if [ "${class_len}" -gt 0 ]; then
		hex_class=$(convert_to_hex "${class}")
		if [ -z "${hex_class}" ]; then
			return 0
		fi

		hex_class_len=$(printf "%02X" "${class_len}")
		if [ "${uci}" = "network" ]; then
			opt125="${opt125}:03:${hex_class_len}${hex_class}"
		else
			opt125="${opt125}:06:${hex_class_len}${hex_class}"
		fi
	fi


	if [ "${uci}" = "network" ]; then
		new_send_opt="$sendopt $opt125"
		uci -q set network."${intf}".sendopts="$new_send_opt"
	else
		new_send_opt="$sendopt$opt125"
		uci -q add_list dhcp."${intf}".dhcp_option="$new_send_opt"
	fi
}

check_for_suboptions() {
	# Check if option 4 and 5 present inside enterprise id 3561
	data=$(echo "${1}" | sed 's/://g')
	len=$(printf "${data}"|wc -c)

	rem_len="${len}"
	while [ $rem_len -gt 8 ]; do
		subopt_present=0

		ent_id="${data:0:8}"
		ent_id=$(printf "%d\n" "0x$ent_id")
		if [ $ent_id -ne 3561 ]; then
			len_val=${data:8:2}
			data_len=$(printf "%d\n" "0x$len_val")
			# add 4 byte for ent_id and 1 byte for len
			data_len=$(( data_len * 2 + 10 ))
			# move ahead data to next enterprise id
			data=${data:"${data_len}":"${rem_len}"}
			rem_len=$(( rem_len - data_len ))
			continue
		fi

		# read the length of enterprise data
		len_val=${data:8:2}
		data_len=$(printf "%d\n" "0x$len_val")
		# add 4 byte for ent_id and 1 byte for len
		data_len=$(( data_len * 2 + 10 ))

		len_val=${data:8:2}
		opt_len=$(printf "%d\n" "0x$len_val")
		if [ $opt_len -eq 0 ]; then
			echo ${subopt_present}
			return 0
		fi

		# populate the option data of enterprise id
		sub_data_len=$(( opt_len * 2))
		# starting 10 means ahead of length field
		sub_data=${data:10:"${sub_data_len}"}

		# parsing of suboption of option 125
		while [ $sub_data_len -gt 0 ]; do
			# get the suboption id
			sub_opt_id=${sub_data:0:2}
			sub_opt_id=$(printf "%d\n" "0x$sub_opt_id")
			case "${sub_opt_id}" in
			"4") subopt_present=1
			;;
			"5") subopt_present=1
			;;
			esac

			if [ ${subopt_present} -eq 1 ]; then
				break;
			fi

			# get the length of suboption
			sub_opt_len=${sub_data:2:2}
			sub_opt_len=$(printf "%d\n" "0x$sub_opt_len")
			sub_opt_len=$(( sub_opt_len * 2 ))

			# add 2 bytes for sub_opt id and sub_opt len field
			sub_opt_end=$(( sub_opt_len + 4 ))

			# update the remaining sub option hex string length
			sub_data_len=$((sub_data_len - sub_opt_end))

			# fetch next sub option hex string
			sub_data=${sub_data:${sub_opt_end}:${sub_data_len}}
		done

		if [ ${subopt_present} -eq 1 ]; then
			break;
		else
			# move ahead data to next enterprise id
			rem_len=$(( rem_len - $data_len ))
			data=${data:"${data_len}":"${rem_len}"}
		fi
	done

	echo ${subopt_present}
}

enable_dhcp_option125() {
	local wan="${1}"
	local reqopts="$(uci -q get network."${wan}".reqopts)"
	local sendopts="$(uci -q get network."${wan}".sendopts)"
	local proto="$(uci -q get network."${wan}".proto)"
	local newreqopts=""
	local newsendopts=""
	local req125_present=0
	local send125_present=0
	local opt125="125:"

	for ropt in $reqopts; do
		case $ropt in
			125) req125_present=1 ;;
			*) ;;
		esac
	done

	for sopt in $sendopts; do
		if [[ "$sopt" == "$opt125"* ]]; then
			send125_present=1
			break
		fi
	done

	if [ "${proto}" = "dhcp" ]; then
		if [ ${req125_present} -eq 0 ]; then
			newreqopts="$reqopts 125"
			uci -q set network."${wan}".reqopts="$newreqopts"
		fi

		if [ ${send125_present} -eq 0 ]; then
			configure_send_op125 "${sendopts}" "${wan}" "network"
		fi
	fi
}

enable_dnsmasq_option125() {
	local lan="${1}"
	local send125_present=0
	local opt125="125,"

	local proto="$(uci -q get dhcp."${lan}".dhcpv4)"
	if [ "${proto}" = "server" ]; then
		opt_list="$(uci -q get dhcp."${lan}".dhcp_option)"
		base_opt=""

		for sopt in $opt_list; do
			if [[ "$sopt" == "$opt125"* ]]; then
				send125_present=$(check_for_suboptions "${sopt:4}")
				base_opt="${sopt}"
				break
			fi
		done

		if [ ${send125_present} -eq 0 ]; then
			uci -q del_list dhcp."${lan}".dhcp_option="${base_opt}"
			configure_send_op125 "${base_opt}" "${lan}" "dhcp"
		fi
	fi
}

configure_gateway_device_info() {
	wan_intf=""
	lan_intf=""

	config_load gateway
	config_get_bool enable global enable '1'
	config_get wan_intf global wan_interface "wan"
	config_get lan_intf global lan_interface "lan"

	if [ "${enable}" -eq 0 ]; then
		return 0
	fi

	# Set dhcp_option 125 for device info if not already configured
	enable_dhcp_option125 "${wan_intf}"

	if [ "${wan_intf}" != "${lan_intf}" ]; then
		# This is extender no need to configure gateway info
		enable_dnsmasq_option125 "${lan_intf}"
	fi
}

configure_gateway_device_info
