#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2012 OpenWrt.org

. /lib/functions/network.sh
. /lib/config/uci.sh

MACSECRETPW="se2cosa3phos9why9taj"
CHILLI=/etc/chilli
WPAD=${CHILLI}/www/wpad.dat
CFGFILE=${CHILLI}/config
FW="/etc/firewall.d/chilli.sh"
DB="/wxa/radius/radius.sqlite3"
DEFNETWORK="10.1.5.0"
DEFMASK="255.255.255.0"

#
# must happen after network
START=99

SERVICE_USE_PID=1
SERVICE_PID_FILE=/var/run/chilli.pid
SERVICE_WRITE_PID=1

cat <<EOF > $FW
#!/bin/sh
#
# Auto generated shell script. Do not modify. Please see /etc/init.d/chilli for details
#
iptables -F chilli_input
iptables -N chilli_input
iptables -C input_cap_rule -j chilli_input || iptables -I input_cap_rule -j chilli_input

iptables -F chilli_forward
iptables -N chilli_forward
iptables -C forwarding_rule -j chilli_forward || iptables -I forwarding_rule -j chilli_forward

iptables -t nat -F chilli_natcensor
iptables -t nat -N chilli_natcensor
iptables -t nat -C prerouting_rule -j chilli_natcensor || iptables -t nat -I prerouting_rule -j chilli_natcensor

#
# reinstate nat rules for chilli users that are logged in
. /etc/chilli/functions
mkdir -p \$NAT_DIR
macs=\`ls \$NAT_DIR\`
for i in \$macs ; do
    nat=\`cat \$NAT_DIR/\$i\`
    eval "\$nat"
done

EOF
chmod a+x $FW

#
# Check for IP validity
# http://stackoverflow.com/a/13778973
is_ip() {
    local ip=$1
 
    if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
        for i in 1 2 3 4; do
            if [ $(echo "$ip" | cut -d. -f$i) -gt 255 ]; then
                return 1
            fi
        done
        return 0
    else
        return 1
    fi
}

do_firewall() {
        # reload the firewall.  Note that restart breaks mwan3 so use reload. But reload
        # does not execute firewall.user.  so execute it manually to load up changes
	fw3 reload
	$FW	
}

section_enabled() {
	config_get_bool enabled "$1" 'enabled' 0
	[ $enabled -gt 0 ]
}

reload() {

        pid=`pgrep chilli`
        [ -n "$pid" ] && kill -TERM $pid
        start
}

start() {
	cap=`grep cap /etc/config/network`
	[ -z "$cap" ] && cat <<EOF >> /etc/config/network

config interface 'cap'
	option proto 'none'
	option ifname 'tun0'

EOF
	config_load chilli
	config_foreach config_chilli 'chilli'	
	config_load chilli
	config_foreach start_chilli 'chilli'
}
				
depends() {
	config_load dhcp
	uci_remove "dhcp" "lan" "ignore"
	uci commit dhcp
	return 0
}

stop() {
	# enable dhcp
	config_load dhcp
	uci_remove "dhcp" "lan" "ignore"
	uci commit dhcp

# 
#	service stop doesnt work because chilli forks and the
#	registered PID does not match the running one
#	service_stop /usr/sbin/chilli
        pid=`pgrep chilli` 
        [ -n "$pid" ] && kill -TERM $pid
	
        do_firewall

	/etc/init.d/dnsmasq restart
}

start_chilli() {
	[ -e /etc/smsg ] || do_create_redirects

	section_enabled "$1" || return 1

	/etc/init.d/dnsmasq restart

	
	# flush accounts that might be haning from previous session.
	cdate=$(date "+%Y-%m-%d %T")
	/usr/bin/sqlite3 $DB "UPDATE radacct SET acctstoptime=\"${cdate}\" WHERE acctstoptime IS NULL OR acctstoptime='';"
	
        chiver=`chilli --version | sed s/[^0-9]//g`
        [ $chiver -gt 130 -a -e $WPAD ] && opt="--wpadpacfile=$WPAD"
	[ -n "$dhcp_opt" ] && opt="$opt --dhcpopt=$dhcp_opt"
	[ -n "$childmax" ] && opt="$opt --childmax=$childmax"
	service_start /usr/sbin/chilli $opt

	sleep 1
	/etc/init.d/dnsmasq restart
}

config_chilli() {
	section_enabled "$1" || return 1

	mkdir -m0755 -p /var/etc
	include /lib/network
	scan_interfaces
	config_get wanif wan ifname

	config_get lan_ifname lan ifname
	config_get lan_ipaddr lan ipaddr	

	mac=`ifconfig $lan_ifname | head -1 | awk '{print $5}' | tr -d ':'`

	cat <<EOF > $CFGFILE
### AUTOGENERATED CONFIGURATION
### DO NOT EDIT
### SEE /etc/config/chilli INSTEAD
HS_WANIF=$wanif            # WAN Interface toward the Internet
HS_RAD_PROTO="pap"
HS_REDIRSSL=on 
HS_SSLKEYFILE=/etc/chilli/cert.pem 
HS_SSLCERTFILE=/etc/chilli/cert.pem
EOF
	
	config_load chilli
	chilli_atom "$1" nasid "$mac" >> $CFGFILE
	chilli_atom "$1" lanif "$lan_ifname" >> $CFGFILE
	chilli_atom "$1" uamlisten "10.1.5.1" >> $CFGFILE
	chilli_atom "$1" dns1 "10.1.5.1" >> $CFGFILE
	chilli_atom "$1" dns2 "8.8.8.8" >> $CFGFILE
	chilli_atom "$1" dns_domain "local" >> $CFGFILE
	chilli_atom "$1" definteriminterval "60" >> $CFGFILE
	chilli_atom "$1" network "$DEFNETWORK" >> $CFGFILE
	chilli_atom "$1" netmask "$DEFMASK" >> $CFGFILE
	chilli_atom "$1" radius >> $CFGFILE
	chilli_atom "$1" radius2 >> $CFGFILE
	chilli_atom "$1" radsecret >> $CFGFILE
	chilli_atom "$1" provider "RedPort" >> $CFGFILE
#	chilli_atom "$1" provider_link "http://www.redportglobal.com" >> $CFGFILE
	chilli_atom "$1" provider_link "http://\$HS_UAMLISTEN/status.php" >> $CFGFILE
	chilli_atom "$1" loc_name "RedPort HotSpot" >> $CFGFILE
	chilli_atom "$1" loc_network "MSS" >> $CFGFILE  # WISPr network name
	chilli_atom "$1" loc_ac "865" >> $CFGFILE       # WISPr phone area code
	chilli_atom "$1" loc_cc "1" >> $CFGFILE         # WISPr phone country code
	chilli_atom "$1" loc_isocc "US" >> $CFGFILE     # WISPr ISO country code
	chilli_atom "$1" tcp_ports "80 443 25 110 22 53 5454 69 5060 5062 3000 137 138 139 445" >> $CFGFILE # white space separated list of tcp ports to allow through to the tun0
	chilli_atom "$1" defsessiontimeout "3600" >> $CFGFILE	 # default session timeout
	chilli_atom "$1" defidletimeout "300" >> $CFGFILE # default idle timeout
	chilli_list "$1" uamallow "redportglobal.com, bogus.com,93.157.3.167,93.157.3.168,202.85.227.245,202.85.227.244" >> $CFGFILE
	chilli_atom "$1" uamformat 'http://\$HS_UAMLISTEN:\$HS_UAMUIPORT/www/login.chi' >> $CFGFILE

	cat <<EOF >> $CFGFILE
HS_UAMSERVER=\$HS_UAMLISTEN
HS_UAMHOMEPAGE=http://\$HS_UAMLISTEN:\$HS_UAMPORT/www/coova.html
HS_MACPASSWD=$MACSECRETPW
EOF
	config_get redirurl "$1" "redireurl"
	config_get tproxy "$1" "tproxy"
	config_get wpad "$1" "wpad"
        config_get wpadhost "$1" "wpadhost"
	config_get wpadurl "$1" "wpadurl"
	config_get wpad_direct "$1" "wpad_direct"
	config_get dhcp_opt "$1" "dhcp_opt"
	config_get childmax "$1" "childmax"
	chilli_list "$1" uamallow "redportglobal.com, bogus.com,93.157.3.167,93.157.3.168,202.85.227.245,202.85.227.244" >> $CFGFILE
        config_get network "$1" network "$DEFNETWORK"
        config_get netmask "$1" netmask "$DEFMASK"

        g_macallow=""
	config_foreach do_macallow mac
	[ -n "$g_macallow" ] && chilli_echo macallow "$g_macallow" >> $CFGFILE
	
        config_load privoxy
	config_foreach do_privoxy privoxy "$tproxy" "$wpad" "$wpadhost" "$wpadurl" "$wpad_direct" "$network/$netmask" "$whitelist"

	# 
	# write config overides to ${CHILLI}/config
	. ${CHILLI}//functions
	writeconfig
	radiusconfig

	#
	# setup firewall redirects
	echo "iptables -I chilli_input -p tcp -m tcp --dport $HS_UAMPORT --dst $HS_UAMLISTEN -j ACCEPT" >> $FW
	echo "iptables -I chilli_input -p tcp -m tcp --dport $HS_UAMUIPORT --dst $HS_UAMLISTEN -j ACCEPT" >> $FW
	for port in $HS_TCP_PORTS; do
	    echo "iptables -I chilli_input -p tcp -m tcp --dport $port --dst $HS_UAMLISTEN -j ACCEPT" >> $FW
	    echo "iptables -I chilli_input -p udp -m udp --dport $port --dst $HS_UAMLISTEN -j ACCEPT" >> $FW
	done
	echo "iptables -I chilli_input -p udp -d 255.255.255.255 --destination-port 67:68 -j ACCEPT" >> $FW
	echo "iptables -I chilli_input -p udp -d $HS_UAMLISTEN --destination-port 67:68 -j ACCEPT" >> $FW
#
# DNS is controlled by whitelisting tcp_ports (see above in tcp_ports. The default is to include port 53 there. So no
# need to have it here.
#	echo "iptables -I chilli_input -p udp --dst $HS_UAMLISTEN --dport 53 -j ACCEPT" >> $FW
	echo "iptables -I chilli_input -p icmp --dst $HS_UAMLISTEN -j ACCEPT" >> $FW
	echo "iptables -A chilli_input  -m conntrack --ctstate DNAT -m comment --comment 'Accept port redirections' -j ACCEPT" >> $FW
	echo "iptables -A chilli_input --dst $HS_UAMLISTEN -j DROP" >> $FW
	echo "iptables -I chilli_input ! -s $HS_NETWORK/$HS_NETMASK -j DROP" >> $FW
	echo "iptables -I chilli_forward -i $HS_LANIF ! -s $HS_NETWORK/$HS_NETMASK -j DROP" >> $FW

        for i in $whitelist ; do
	    is_ip $i
	    if [ $? -eq 0 ]; then
                 echo "iptables -I chilli_forward -i $HS_LANIF -s $HS_NETWORK/$HS_NETMASK -d $i -j ACCEPT" >> $FW
	    fi
        done

#
# this no longer works since we moved the firewall rules to /etc/firewall.d/chilli.sh
# so the firewall DO_NO_MODIFY rules are no longer changed when chilli is enabled/disabled
#
#        sum=`sum /etc/firewall.user`
#        nsum=`sum /tmp/firewall.user`
#        if [ "$nsum" != "$sum" ]; then
#
#      	    # openup firewall
#	    config_load 'firewall' 
#	    config_foreach set_firewall rule
#	    uci commit firewall
#
#	    do_firewall
#	fi

	do_firewall

	# disable dhcp on the lan.
	uci_set "dhcp" "lan" "ignore" "1"
	uci commit dhcp


	return 0
}

do_create_redirects() {

mkdir -p /var/www

cat > /var/www/index.php <<EOF
<?php

\$chilli = shell_exec("uci -q get chilli.@chilli[0].enabled");

if ( \$chilli == "1" && \$_SERVER['SERVER_ADDR'] == "$HS_UAMLISTEN" && \$_SERVER['SERVER_PORT'] == "80" ) {
        \$rurl="http://$HS_UAMLISTEN:$HS_UAMUIPORT/www/login.chi";
} else {
        \$rurl="/cgi-bin/luci";
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="refresh" content="0; URL=<?php print \$rurl ?>" />
</head>
<body onunload="" style="background-color: white">
<a style="color: black; font-family: arial, helvetica, sans-serif;" href="<?php print \$rurl ?>">LuCI - Lua Configuration Interface</a>
</body>

EOF

cat > /var/www/status.php <<EOF
<?php
\$rurl="http://$HS_UAMLISTEN:$HS_UAMUIPORT/www/status.chi";
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="refresh" content="0; URL=<?php print \$rurl ?>" />
</head>
<body style="background-color: white">
<a style="color: black; font-family: arial, helvetica, sans-serif;" href="<?php print \$rurl ?>">LuCI - Lua Configuration Interface</a>
</body>

EOF

cat > /var/www/logout.php <<EOF
<?php
\$rurl="http://logout/";
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="refresh" content="0; URL=<?php print \$rurl ?>" />
</head>
<body style="background-color: white">
<a style="color: black; font-family: arial, helvetica, sans-serif;" href="<?php print \$rurl ?>">LuCI - Lua Configuration Interface</a>
</body>

EOF

ln -sf /var/www/index.php /var/www/login.php
ln -sf /var/www/logout.php /var/www/logoff.php
[ -e /www/index.html ] && rm -f /www/index.html
[ -h /www/index.php ] || ln -sf /var/www/index.php /www/index.php
[ -h /www/status.php ] || ln -sf /var/www/index.php /www/status.php
[ -h /www/login.php ] || ln -sf /var/www/login.php /www/login.php
[ -h /www/logout.php ] || ln -sf /var/www/logout.php /www/logout.php
[ -h /www/logoff.php ] || ln -sf /var/www/logoff.php /www/logoff.php
}

do_privoxy() {
    tproxy="$2"
    wpad="$3"
    wpadhost="$4"
    wpadurl="$5"
    wpad_direct="$6"
    netaddr="$7"
    whitelist="$8"

    config_get proxy_port "$1" listen_port
    config_get transparent "$1" "transparent_proxy"
    chilli_echo proxy "${lan_ipaddr}:${proxy_port}" >> $CFGFILE

    if [ -n "$tproxy" -a "$tproxy" = "1" ]; then
# chilli forwards to proxy server after authentication.  Does not work with SSL
#        chilli_echo postauth_proxy     "$lan_ipaddr" >> $CFGFILE
#        chilli_echo postauth_proxyport "$proxy_port" >> $CFGFILE

# conup script creates redirect to proxy works for both ssl and http however rules are lost if firewall manipulation happens during chilli session. i.e. fw3 restart or reload
	chilli_echo conup "${CHILLI}/conup.sh" >> $CFGFILE
	chilli_echo condown "${CHILLI}/condown.sh" >> $CFGFILE
    fi

    # by pass proxy for all whitelisted 
    for i in $whitelist ; do
	is_ip $i
	if [ $? -eq 0 ]; then
            echo "iptables -t nat -A chilli_natcensor -i $lan_ifname -p tcp --src $netaddr --dst $i -j ACCEPT" >> $FW
	fi
    done
# this method breaks the redirect because DNAT happens in PREROUTING before so traffic never hits the captive portal. Use conup/condown above.
#         echo "iptables -t nat -A chilli_natcensor -i $lan_ifname -p tcp --src $netaddr ! --dst $netaddr --dport 80 -j DNAT --to-destination ${proxy_addr}" >> $FW
#        [ "$ssl_tproxy" = "1" ] && echo "iptables -t nat -A chilli_natcensor -i $lan_ifname -p tcp --src $netaddr ! --dst $netaddr --dport 443 -j DNAT --to-destination ${lan_ipaddr}:888" >> $FW

    if [ "$transparent" = "1" ]; then
        uci_set privoxy "$1" "transparent_proxy" "0"
        uci commit privoxy
	/etc/init.d/privoxy restart
    fi

    # setup wpad
    [ -z "$wpad" -o  "$wpad" = "0" ] && rm -f $WPAD && return

    if [ -z "$wpad_direct" -o "$wpad_direct" = "0" ] ; then
cat <<EOF > $WPAD
function FindProxyForURL(url, host)
{
    if (isPlainHostName(host)         ||
        shExpMatch(host, "*.local")   ||
        shExpMatch(host, "10.*")      ||
        shExpMatch(host, "192.168.*") ||
        shExpMatch(host, "172.16.*")  ||                        
        shExpMatch(host, "172.17.*")  || 
        shExpMatch(host, "172.18.*")  || 
        shExpMatch(host, "172.19.*")  || 
        shExpMatch(host, "172.20.*")  || 
        shExpMatch(host, "172.21.*")  || 
        shExpMatch(host, "172.22.*")  || 
        shExpMatch(host, "172.23.*")  || 
        shExpMatch(host, "172.24.*")  || 
        shExpMatch(host, "172.25.*")  || 
        shExpMatch(host, "172.26.*")  || 
        shExpMatch(host, "172.27.*")  ||   
        shExpMatch(host, "172.28.*")  || 
        shExpMatch(host, "172.29.*")  || 
        shExpMatch(host, "172.30.*")  || 
        shExpMatch(host, "172.31.*")  || 
	shExpMatch(host, "127.0.0.1") || 
	shExpMatch(host, "*logout*")  ||
EOF

for i in  $wpadhost  ; do
    echo "	shExpMatch(host, \"$i\") || " >> $WPAD
done

for i in $wpadurl ; do
    echo "	shExpMatch(url, \"$i\") || " >> $WPAD
done

cat <<EOF >> $WPAD
	shExpMatch(url, "*status.chi") ||
	shExpMatch(url, "*login.chi"))
        return "DIRECT";

    return "PROXY ${lan_ipaddr}:${proxy_port}";
}
EOF

    else
cat <<EOF > $WPAD
function FindProxyForURL(url, host)
{
	return "DIRECT";
}
EOF
    fi

}

do_macallow() {
    config_get macaddr "$1" "macaddr"
    [ -n "$g_macallow" ] && g_macallow="$g_macallow,"
    g_macallow="${g_macallow}${macaddr}"
}

set_firewall() {
    config_get name "$1" "name"
    [ "$name" = "PASS DNS - DO_NOT_MODIFY" -o "$name" = "DNS - DO_NOT_MODIFY" -o "$name" = "HTTP - DO_NOT_MODIFY" -o "$name" = "HTTPS - DO_NOT_MODIFY" -o "$name" = "FTP - DO_NOT_MODIFY" -o "$name" = "ALL - DO_NOT_MODIFY" ]  && {
	config_get_bool enabled "$1" "enabled" 
	[ "$enabled" != "" ] && uci_remove firewall "$1" "enabled"
    }
}

chilli_echo() {
	echo "HS_$(echo $1|tr 'a-z' 'A-Z')=\"$2\"" | sed -e 's/\$/\\\$/g' -e 's/\\\\//g'
}

chilli_atom() {
	local SECTION=$1
	local OPTION=$2
	local DEFAULT=$3

	config_get _value "$SECTION" "$OPTION"

	[ -z "$_value" ] && _value="$DEFAULT"
	[ -n "$_value" ] && chilli_echo "$OPTION" "$_value" 
}

chilli_flag() {
	local SECTION=$1
	local OPTION=$2
	local TRUE="${3:-1}"
	local FALSE="${4:-0}"

	config_get_bool _value "$SECTION" "$OPTION" 0

	[ "$_value" -eq "1" ] && _value="$TRUE" || _value="$FALSE"
	chilli_echo "$OPTION" "$_value" 
}

chilli_list() {
	local SECTION=$1
	local OPTION=$2
	local DEFAULT=$3

	config_get _value "$SECTION" "$OPTION"
	[ -n "$_value" -o -n "$DEFAULT" ] && {
		list="$DEFAULT"
		for entry in $_value; do
			if [ -z "$list" ]; then
			   list="$entry"
			else
			   list="$list,$entry"
			fi
		done
		chilli_echo "$OPTION" "$list"
	}
}








