#!/bin/sh -f

po_domain="alterator-net-pptp"
retries=3

. alterator-sh-functions
. alterator-net-functions

### interface helpers

# sleep order is on purpose: dhcp runs in background
start_iface()
{
	[ -n "$1" ] || return
	write_debug 'start_iface[%s]:' "$1"
	for i in `seq 1 $retries`; do 
		write_debug '.'
		ifcheckup "$1" && break
		ifup "$1"
		sleep 1
	done
	write_debug '\n'
}

# if it's up, ensure it's down first, then back up
stop_iface()
{
	[ -n "$1" ] || return
	write_debug 'stop_iface[%s]:' "$1"
	for i in `seq 1 $retries`; do 
		write_debug '.'
		ifcheckup "$1" || break
		ifdown "$1"
		sleep 1
	done
	write_debug '\n'
}

# do our best so that $1 is working
# FIXME: this should become redundant when etcnet gets fixed
# (https://bugzilla.altlinux.org/show_bug.cgi?id=14021)
bring_up()
{
	[ -n "$1" ] || return
	write_debug 'bring_up[%s]\n' "$1"

        # ensure underlying iface is up
        start_iface "$in_iface"

	# workaround: etcnet might try to bring up ppp too early
	# when underlying eth is configured via dhcp and is down
	sleep 1

        # try to wait until ppp0 might go down (otherwise 
        # additional static route might not appear)
        stop_iface "$1"
        start_iface "$1"
}

################### interface modificators

ppp0_if_there()
{
		# FIXME: it's a kluge // mike on 20080422
		# if ppp0 is dialer-initiated, not static iface (pptp/pppoe)
		# then echo it too
		/sbin/ip li sh \
		| grep -q ": ppp0: " \
		&& [ ! -d /etc/net/ifaces/ppp0 ] \
		&& write_enum_item 'ppp0'
}

read_connection()
{
	local name="/etc/net/ifaces/$1"

	# mppe is off by default with pppd
	write_bool_param 'mppe' "$(read_ppp_option1 "$name" 'require-mppe' 'nomppe')"

	# we prefer it to work by default, at least when already configured
	# and for just created interfaces
	! [ -x "$name/ifup-pre" -a -x "$name/ifdown-post" ]
	write_bool_param 'save_route' "$?"
	local SAVE_GW="#t"
	[ -x "$name/ifup-pre" -a -x "$name/ifdown-post" ] || SAVE_GW="#f"
	
	# usually default route needs to be replaced
	# /etc/ppp/options should hold "replacedeaultroute",
	# $name/pppoptions should hold "defaultroute" then; see pppd(8)
	write_bool_param def_via_vpn "$(read_ppp_option1 "$name" 'defaultroute' 'nodefaultroute' 'yes')"

	write_bool_param persist "$(read_ppp_option1 "$name" 'persist' 'nopersist')"

	local info=
	ifcheckup "$1" && info="`_ "connection established"`" || info="`_ "connection down"`"
	write_string_param info "$info"

	write_string_param server "$(read_iface_option "$name"  PPTP_SERVER)"
	write_string_param iface "$(read_iface_option "$name" REQUIRES)"
	write_string_param login "$(read_ppp_option "$name" user)"
	write_bool_param onboot "$(read_iface_option "$name" ONBOOT)"
}

write_save_route()
{
    if test_bool "$in_save_route";then
	DEF_GW="`/sbin/ip ro | awk '/^default via/ { print $3; exit; }'`"

	[ -n "$DEF_GW" ] || return
	[ "$DEF_GW" != "$in_server" ] || return

	printf "#!/bin/sh\n/sbin/ip route add %s via %s\n" "$in_server" "$DEF_GW" > "$name/ifup-pre"
	printf "#!/bin/sh\n/sbin/ip route del %s via %s\n" "$in_server" "$DEF_GW" > "$name/ifdown-post"
	chmod +x "$name/ifup-pre" "$name/ifdown-post"
    else
	[ -x "$name/ifdown-post" ] && "$name/ifdown-post"
	rm -f "$name/ifup-pre" "$name/ifdown-post"
    fi
}

write_connection()
{
	[ "$1" = "/" ] && return

	local name="/etc/net/ifaces/$1"

	[ "$in_onboot" = "#t" ] && in_onboot="yes" || in_onboot="no"

	[ -d "$name" ] || mkdir -- "$name"

	[ -n "$in_server" ] && write_iface_option "$name" PPTP_SERVER "$in_server"

	# e.g. ppp0 might be a dynamic dial-up interface
	[ -f "/etc/net/ifaces/$in_iface/options" ] && write_iface_option "$name" REQUIRES "$in_iface"
	[ -n "$in_iface" ] && write_iface_option "$name" ONBOOT "$in_onboot"
	
	[ -n "$in_login" ] && write_ppp_option "$name" user "$in_login"
	[ -n "$in_password" ] && write_ppp_option "$name" password $(echo "$in_password"|sed -e 's/["]/\\\\&/g')

	test_bool "$in_mppe"
	write_ppp_option1 "$name" 'require-mppe' 'nomppe' "$?"
	test_bool "$in_def_via_vpn"
	write_ppp_option1 "$name" 'defaultroute' 'nodefaultroute' "$?"
	test_bool "$in_persist"
	write_ppp_option1 "$name" 'persist' 'nopersist' "$?"
	write_save_route

	[ "$in_onboot" = "yes" ] && bring_up "$1"
	return 0
}

new_connection()
{
    local name="/etc/net/ifaces/$1"

    mkdir -p -- "$name"

    write_iface_option "$name" TYPE ppp
    write_iface_option "$name" PPPTYPE pptp

    # vsu@ proposed that nodeflate, nobsdcomp be disabled 
    # by default after debugging a problem in community@
    # ...and that mtu be clamped at 1460 or 1400
    # usepeerdns https://bugzilla.altlinux.org/show_bug.cgi?id=14116
    cat>"$name/pppoptions"<<EOF
nodeflate
nobsdcomp
mtu 1400
usepeerdns
EOF
    chmod o-rw "$name/pppoptions" # deny others reading the password
}

delete_connection()
{
	[ "$1" = "/" ] && return
	local name="/etc/net/ifaces/$1"

	ifdown "$1"
	rm -rf -- "$name"
}

start_connection()
{
	write_debug 'start_connection: [%s]\n' "$1"
	[ -z "$1" -o "$1" = "/" ] && return
	bring_up "$1"
}

stop_connection()
{
	write_debug 'stop_connection: [%s]\n' "$1"
	[ -z "$1" -o "$1" = "/" ] && return
	stop_iface "$1"
}

on_message()
{
	case "$in_action" in
		##information
		constraints)
			local required="$([ "$in_orig_action" = "new" ] && echo "#t" || echo "#f")"
			echo '('
			printf 'server (match ("^[[:alnum:].-]+$" "%s") label "%s")' \
				 "$(_ "invalid server name")" "$(_ "Server")"
			printf 'name  (required %s match ("^ppp[0-9]+$"  "%s")  default "%s" label "%s")' \
					"$required" \
					"`_ "should be ppp[number]"`" \
					"$(next_ppp)" \
					"`_ "Connection"`"
			printf 'password  (required %s label "%s")' \
				"$required" \
				"`_ "Password"`"
			echo ')'
			;;
		##actions
		list)
			echo '('
			case "$in__objects" in
			    avail_connection)
				list_ppp 'pptp'|write_enum
				;;
			    avail_iface)
				list_eth|write_enum
				# FIXME: add ppp0 in case it's active: customer needs PPTP over PPP
				ppp0_if_there
				;;
			    avail_state)
				write_enum_item "ignore" "`_ "don't change"`" #'
				write_enum_item "start" "`_ "start"`"
				write_enum_item "stop" "`_ "stop"`"
				write_enum_item "restart" "`_ "restart"`"
				;;
			esac
			echo ')'
			;;
		read) 
			echo '('
			local name="$in_name"
			[ -n "$in_new" ] && name="$in_new_name"
			[ -n "$name" ] || name="$(list_ppp 'pptp'|head -n1)"

			write_string_param new_name "$(next_ppp)"
			write_string_param name "$name"
			[ -n "$name" ] && read_connection "$name"
			echo ')'
			;;
		write)
			if [ -n "$in_new" ]; then
			    [ -n "$in_new_name" ] && new_connection "$in_new_name"
			    write_nop
			elif [ -n "$in_delete" ];then
			    [ -n "$in_name" ] && delete_connection "$in_name"
			    write_nop
			elif [ -n "$in_commit" ];then
			    write_connection "$in_name"
			    case "$in_status" in
				start) start_connection "$in_name";;
				stop) stop_connection "$in_name";;
				restart)
				    stop_connection "$in_name"
				    start_connection "$in_name"
				    ;;
			    esac
			    write_nop
			else
			    write_nop
			fi
			;;
		*)
			echo '#f'
			;;
	esac
}

message_loop
