#!/bin/sh

[ -z "$script_type" ] && {
	logger -t "openvpn(proto)" -p daemon.warn "hotplug: variable 'script_type' not found"
	exit
}

[ -z "$INTERFACE" ] && {
	logger -t "openvpn(proto)" -p daemon.warn "hotplug: variable 'INTERFACE' not found"
	exit
}

. /lib/functions.sh
. /lib/netifd/netifd-proto.sh

mask2prefix() {
	local mask="$1"
	local n=0
	local IFS=.
	for o in $mask; do
		case $o in
			255) n=$((n+8)) ;;
			254) n=$((n+7)) ;;
			252) n=$((n+6)) ;;
			248) n=$((n+5)) ;;
			240) n=$((n+4)) ;;
			224) n=$((n+3)) ;;
			192) n=$((n+2)) ;;
			128) n=$((n+1)) ;;
			0)   break     ;;
			*)   break     ;;
		esac
	done
	echo "$n"
}

parse_cidr6() {
	local val="$1"
	local def_plen="$2"
	local addr="${val%/*}"
	local plen="${val#*/}"
	[ "$addr" = "$plen" ] && plen="$def_plen"
	echo "$addr $plen"
}

case "$script_type" in
	up)
		nohostroute="$(uci_get network "$INTERFACE" nohostroute)"
		proto_init_update "$dev" 1

		[ -n "$ifconfig_local" ] && proto_add_ipv4_address "$ifconfig_local" "${ifconfig_netmask:-255.255.255.255}"

		[ -n "$trusted_ip" ] && {
			if [ -n "$route_net_gateway" -a "$route_net_gateway" != "0.0.0.0" -a "${nohostroute}" != "1" ]; then
				proto_add_host_dependency "$INTERFACE" "$trusted_ip"
			fi
		}

		[ -n "$route_vpn_gateway" ] && proto_add_ipv4_route "0.0.0.0" 0 "$route_vpn_gateway"

		i=0
		while :; do
			i=$((i+1))
			eval "net=\$route_network_$i mask=\$route_netmask_$i gw=\$route_gateway_$i"
			[ -z "$net" ] && break
			[ -z "$mask" ] && continue

			plen=$(mask2prefix "$mask")
			proto_add_ipv4_route "$net" "$plen" "$gw"
		done

		if [ "$IPV6" = "1" ]; then
			if [ -n "$ifconfig_ipv6_local" ]; then
				read -r v6addr v6plen <<-EOF
					$(parse_cidr6 "$ifconfig_ipv6_local" "${ifconfig_ipv6_netbits:-128}")
				EOF
				proto_add_ipv6_address "$v6addr" "$v6plen"
			fi

			[ -n "$trusted_ip6" ] && {
				# to detect net_gateway_ipv6, source routing on wan6 has to be disabled
				# consider removing check for net_gateway_ipv6
				if [ -n "$net_gateway_ipv6" -a "$net_gateway_ipv6" != "::" -a "${nohostroute}" != "1" ]; then
					proto_add_host_dependency "$INTERFACE" "$trusted_ip6"
				fi
			}

			[ -n "$ifconfig_ipv6_remote" ] && proto_add_ipv6_route "::" 0 "$ifconfig_ipv6_remote"

			i=0
			while :; do
				i=$((i+1))
				eval "net=\$route_ipv6_network_$i gw=\$route_ipv6_gateway_$i"
				[ -z "$net" ] && break

				read -r v6net v6plen <<-EOF
					$(parse_cidr6 "$net" 128)
				EOF
				proto_add_ipv6_route "$v6net" "$v6plen" "$gw"
			done
		fi

		[ -n "$tun_mtu" ] && json_add_int mtu "$tun_mtu"

		i=0
		while :; do
			i=$((i+1))
			eval "option=\$foreign_option_$i"
			[ -z "$option" ] && break

			set -- $option
			[ "$1" != "dhcp-option" ] && continue

			case "$2" in
				DNS)           proto_add_dns_server "$3" ;;
				DOMAIN*)       proto_add_dns_search "$3" ;; # Matches DOMAIN and DOMAIN-SEARCH
			esac
		done

		proto_send_update "$INTERFACE"
	;;

	down)
		proto_init_update "$dev" 0
		proto_send_update "$INTERFACE"
	;;
esac

ACTION="$script_type"
INSTANCE="$INTERFACE"

export ACTION="$ACTION"
export INSTANCE="$INSTANCE"
exec /sbin/hotplug-call openvpn "$@"
