#!/bin/sh

. /lib/functions.sh
. /usr/share/libubox/jshn.sh
. /lib/netmode/netmode_helpers.sh

source "/etc/device_info"

l2_mcast_config() {
	# configure L2 mcast config for snooping
	logger -s -p user.info -t "netmode" "Generating L2 mcast configuration"

	# remove proxy sections
	uci -q delete mcast.igmp_proxy_1
	uci -q delete mcast.mc_proxy_MLD

	# add igmp_snooping section
	uci -q set mcast.igmp_snooping_1=snooping
	uci -q set mcast.igmp_snooping_1.enable='1'
	uci -q set mcast.igmp_snooping_1.proto='igmp'
	uci -q set mcast.igmp_snooping_1.version='2'
	uci -q set mcast.igmp_snooping_1.robustness='2'
	uci -q set mcast.igmp_snooping_1.query_interval='125'
	uci -q set mcast.igmp_snooping_1.query_response_interval='100'
	uci -q set mcast.igmp_snooping_1.last_member_query_interval='10'
	uci -q set mcast.igmp_snooping_1.fast_leave='1'
	uci -q set mcast.igmp_snooping_1.snooping_mode='2'
	uci -q set mcast.igmp_snooping_1.interface='br-lan'
	uci -q add_list mcast.igmp_snooping_1.filter='239.0.0.0/8'

	# add mld_snooping section
	uci -q set mcast.mld_snooping_1=snooping
	uci -q set mcast.mld_snooping_1.enable='1'
	uci -q set mcast.mld_snooping_1.proto='mld'
	uci -q set mcast.mld_snooping_1.version='2'
	uci -q set mcast.mld_snooping_1.robustness='2'
	uci -q set mcast.mld_snooping_1.query_interval='125'
	uci -q set mcast.mld_snooping_1.query_response_interval='100'
	uci -q set mcast.mld_snooping_1.last_member_query_interval='10'
	uci -q set mcast.mld_snooping_1.fast_leave='1'
	uci -q set mcast.mld_snooping_1.snooping_mode='2'
	uci -q set mcast.mld_snooping_1.interface='br-lan'

	uci -q commit mcast
}

create_vlan_device() {
	local ifname="$1"
	local vlanid="$2"
	local qinq="$3"
	local name=""
	
	if uci -q add network device; then
		if [ "$qinq" = "1" ]; then
			uci -q set network.@device[-1].type="8021ad"
		else
			uci -q set network.@device[-1].type="8021q"
		fi
		name="${ifname}.${vlanid}"
		uci -q set network.@device[-1].name="$name"
		uci -q set network.@device[-1].ifname="$ifname"
		uci -q set network.@device[-1].vid="$vlanid"

		echo "$name"
	fi
}

# if svlanid is present, 8021ad section will be created
# if cvlanid is present, 8021q section will be created
# if both are present, 8021q section will be created on top of 8021ad
# if none are present, ifname will be returned
add_vlan_device() {
	local ifname="$1"
	local cvlanid="$2"
	local svlanid="$3"
	local dev_name="$ifname"

	[ -n "$ifname" ] || return

	if [ -n "$svlanid" ]; then
		dev_name="$(create_vlan_device "$ifname" "$svlanid" "1")"
	fi
	if [ -n "$dev_name" ] && [ -n "$cvlanid" ]; then
		dev_name="$(create_vlan_device "$dev_name" "$cvlanid" "0")"
	fi

	echo "$dev_name"
}

lanlist_to_ifnames() {
	local list="$1"
	local out=""
	local lan ifname
	local idx=0

	[ -n "$list" ] || { echo ""; return; }

	IFS=','
	for lan in $list; do
		# just to be safe
		if [ "$idx" -gt 255 ]; then
			break
		fi
		idx="$((idx + 1))"

		ifname="$(uci -q get network.$lan.name)"
		[ -n "$ifname" ] || continue

		if [ -z "$out" ]; then
			out="$ifname"
		else
			out="$out,$ifname"
		fi
	done
	unset IFS

	echo "$out"
}

l2_network_config() {
	logger -s -p user.info -t "netmode" "Generating L2 network configuration"

	# Configure L2 Network Mode
	uci -q set network.lan=interface
	uci -q set network.lan.proto='dhcp'
	uci -q set network.lan.vendorid="$(uci -q get network.wan.vendorid)"
	uci -q set network.lan.clientid="$(uci -q get network.wan.clientid)"
	uci -q set network.lan.reqopts="$(uci -q get network.wan.reqopts)"
	uci -q set network.lan.sendopts="$(uci -q get network.wan.sendopts)"
	uci -q set network.lan.device='br-lan'
	uci -q set network.lan.force_link='1'

	uci -q set network.lan6=interface
	uci -q set network.lan6.proto='dhcpv6'
	uci -q set network.lan6.device='@lan'
	uci -q set network.lan6.reqprefix='no'

	uci -q set network.wan.disabled='1'
	uci -q set network.wan6.disabled='1'

	uci -q delete network.br_lan.ports
	uci -q set network.br_lan.bridge_empty='1'

	# delete interfaces apart from lan, lan6, wan, wan6
	delete_extra_interfaces
	# delete existing vlan and macvlan sections to prevent clashes
	delete_vlan_and_macvlan_sections

	# convert LAN1,LAN2,LAN3 to eth1,eth2,eth3
	converted_port_list="$(lanlist_to_ifnames "$NETMODE_port_list")"

	add_port_to_br_lan() {
		port="$1"
		[ -n "$port" -a -d /sys/class/net/$port ] || continue

		if [ -n "$converted_port_list" ]; then
			# Check if $port appears as an exact item in comma-separated converted_port_list
			case ",$converted_port_list," in
				*,"$port",*) ;;        # match , do nothing
				*) continue ;;         # no match , skip this port
			esac
		fi

		# get the vlan device name from port name
		device_name="$(add_vlan_device "$port" "$NETMODE_lan_cvlanid" "$NETMODE_lan_svlanid")"
		uci add_list network.br_lan.ports="$device_name"
	}

	if [ -f /etc/board.json ]; then
		json_load_file /etc/board.json
		json_select network
		json_select lan
		if json_is_a ports array; then
			json_for_each_item add_port_to_br_lan ports
		else
			json_get_var device device
			[ -n "$device" ] && uci add_list network.br_lan.ports="$device"
		fi
		json_select ..
		json_select wan 2>/dev/null
		json_get_var device device
		# get the vlan device name from port name
		device_name="$(add_vlan_device "$device" "$NETMODE_wan_cvlanid" "$NETMODE_wan_svlanid")"
		[ -n "$device_name" ] && uci add_list network.br_lan.ports="$device_name"
		json_cleanup
	fi

	uci -q commit network

	# Disable DHCP Server
	uci -q set dhcp.lan.ignore=1
	uci -q commit dhcp
	/etc/init.d/odhcpd disable

	# Disable SSDPD
	uci -q set ssdpd.ssdp.enabled="0"
	uci -q commit ssdpd

	# Update CWMP Agent WAN Interface
	uci -q set cwmp.cpe.default_wan_interface="lan"
	uci -q commit cwmp

	# Update gateway WAN Interface
	uci -q set gateway.global.wan_interface="lan"
	uci -q commit gateway

	# disable firewall
	uci -q set firewall.globals.enabled="0"
	uci -q commit firewall
}

l2_network_config
l2_mcast_config

# If device is already boot-up, assume netmode changed during runtime
if [ -f /var/run/boot_complete ]; then
	/etc/init.d/odhcpd stop 2>/dev/null
	for config in network dhcp ssdpd cwmp gateway firewall mcast; do
		ubus call uci commit "{\"config\":\"$config\"}"
		sleep 1
	done
fi
