#!/bin/sh

BASEDIR=$(dirname $0)/../share/hnetd/
. $BASEDIR/utils.script

# iptables 1.4.14 does not have this; 1.4.21 does. it seems crucial for this
# to work correctly though.. sigh.
iptables_wait () {
    [ -n "$checked_iptables_wait" ] && echo "$have_iptables_wait" && return
    checked_iptables_wait=1
    if iptables -h | grep -q " --wait"; then
        have_iptables_wait="-w"
    fi
    iptables_wait
}

echo "[hnetd-backend] $*"

case "$1" in
dhcpv4client)
	[ "$2" = 1 ] && export NODEFAULT=1
	[ -n "$3" ] && export METRIC=$3
	[ -n "$4" ] && export CUSTOMROUTES=$4
	exec busybox udhcpc -f -t 1000000000 -i "$2" -x "hostname:$(hostname)" -x "0x4d:07484f4d454e4554" -s $BASEDIR/dhcp.script
	;;

dhcpv6client)
	exec odhcp6c -t120 -P0 -F -s $BASEDIR/dhcpv6.script -u HOMENET "$2"
	;;

setfilter|unsetfilter)
	[ "$1" = "setfilter" ] && act="-A" || act="-D"
        ip6tables $act INPUT -i "$2" -s fe80::/10 -d fe80::/10 -p udp -m udp --sport 547 --dport 546 -j ACCEPT `iptables_wait`
	for cmd in iptables ip6tables; do
		case "$cmd" in
			iptables)
				reject="icmp-port-unreachable"
				;;
			ip6tables)
				reject="icmp6-port-unreachable"
				;;
		esac
                $cmd -L MINIUPNPD `iptables_wait` > /dev/null 2>&1 && \
                    $cmd $act FORWARD -i "$2" ! -o "$2" -j MINIUPNPD `iptables_wait`
		$cmd $act FORWARD -i "$2" -p tcp -m conntrack --ctstate NEW,INVALID -j REJECT --reject-with tcp-reset `iptables_wait`
		$cmd $act FORWARD -i "$2" -m conntrack --ctstate NEW,INVALID -j REJECT --reject-with "$reject" `iptables_wait`
		$cmd $act INPUT -i "$2" -p tcp -m conntrack --ctstate NEW,INVALID -j REJECT --reject-with tcp-reset `iptables_wait`
		$cmd $act INPUT -i "$2" -m conntrack --ctstate NEW,INVALID -j REJECT --reject-with "$reject" `iptables_wait`

	done
	iptables -t nat $act POSTROUTING -o "$2" -j MASQUERADE `iptables_wait`
        iptables -L MINIUPNPD > /dev/null 2>&1 && \
            iptables -t nat $act PREROUTING -i "$2" -j MINIUPNPD `iptables_wait` && \
            iptables -t mangle $act PREROUTING -i "$2" -j MINIUPNPD `iptables_wait`
	;;

newaddr|deladdr)
	[ "$1" = "newaddr" ] && act="replace" || act="del"
	[ -n "$4" -a -n "$5" ] && args="preferred_lft $4 valid_lft $5" || args=""
	ip address $act "$3" dev "$2" $args
	killall -q -SIGHUP odhcpd
	;;

newprefixroute|delprefixroute)
	[ "$1" = "newprefixroute" ] && act="replace" || act="del"
	ip -6 route "$act" unreachable "$2" metric 2147483646
	;;

newblocked|delblocked)
	[ "$1" = "newblocked" ] && act="-A" || act="-D"
	case "$3" in
		*.*)
			cmd="iptables"
			reject="icmp-port-unreachable"
		;;
		*)
			cmd="ip6tables"
			reject="icmp6-port-unreachable"
		;;
	esac

	$cmd $act FORWARD -i "$2" -d "$3" -p tcp -j REJECT --reject-with tcp-reset `iptables_wait`
	$cmd $act FORWARD -i "$2" -d "$3" -j REJECT --reject-with "$reject" `iptables_wait`

	$cmd $act FORWARD -o "$2" -s "$3" -p tcp -j REJECT --reject-with tcp-reset `iptables_wait`
	$cmd $act FORWARD -o "$2" -s "$3" -j REJECT --reject-with "$reject" `iptables_wait`
	;;

startdhcp)
	dhcpv4=disabled
	dhcpv6=disabled
	stateful=0

	[ -n "$3" ] && dhcpv4=server
	[ -n "$4" ] && stateful=1
	[ -n "$5" ] && dhcpv6=server

	uci batch <<-EOF
	set dhcp.$2=dhcp
	set dhcp.$2.ifname=$2
	set dhcp.$2.ra=server
	set dhcp.$2.dhcpv4=$dhcpv4
	set dhcp.$2.dhcpv6=$dhcpv6
	set dhcp.$2.pd_manager=$6
	set dhcp.$2.ra_management=$stateful
	set dhcp.$2.filter_class=HOMENET
	commit dhcp
EOF
	pidof odhcpd && killall -SIGHUP odhcpd || odhcpd &
	;;

stopdhcp)
	uci batch <<-EOF
	delete dhcp.$2
	commit dhcp
EOF
	killall -q -SIGHUP odhcpd
	;;

setdhcpv6)
	[ -z "$DNS" ] && exit 0

        # DNS = external DNS server list.
        # We pass it along to guests only.

        IDNS=""
        [ -n "$GUEST" ] && IDNS="$DNS"
	uci batch <<-EOF
	set dhcp.$2=dhcp
	set dhcp.$2.dns="$IDNS"
	set dhcp.$2.domain="$SEARCH"
	set dhcp.$2.dhcpv6_raw="$PASSTHRU"
	set dhcp.$2.ra_default="$RA_DEFAULT"
	commit dhcp
EOF
	killall -q -SIGHUP odhcpd
        update_resolv "hnetd" "$2" "$DNS"
	;;

newnat)
	rule="hnet_snat_$1"
	iptables -t nat -N "$rule" `iptables_wait`
	iptables -t nat -I POSTROUTING -o "$1" -j "$rule" `iptables_wait`
	if [ -z "$4" ]; then
		iptables -t nat -A "$rule" -d "$2" -j ACCEPT `iptables_wait`
		iptables -t nat -A "$rule" -j SNAT --to-source "$3" `iptables_wait`
	else
		iptables -t nat -A "$rule" -d "$3/$4" -j SNAT --to-source "$3" `iptables_wait`
	fi
	;;

delnat)
	rule="hnet_snat_$1"
	iptables -t nat -D POSTROUTING -o "$1" -j "$rule" `iptables_wait`
	iptables -t nat -F "$rule" `iptables_wait`
	iptables -t nat -X "$rule" `iptables_wait`
	;;

esac
