#!/bin/sh
#
# Copyright (c) 2006-2012 David Bird (Coova Technologies)
# Licensed under Gnu General Public License.
# http://coova.github.io/
#

IPTABLES=/sbin/iptables
IFCONFIG=/sbin/ifconfig

CHILLI=/etc/chilli
RUN_D=/var/run
SBIN=/usr/sbin

[ -f /etc/sysconfig/chilli ] && . /etc/sysconfig/chilli

[ -f $CHILLI/defaults ] && . $CHILLI/defaults
[ -f $CHILLI/config ]   && . $CHILLI/config

[ -n "$DHCPIF" ] && [ -d "$CHILLI/$DHCPIF" ] && {
    CHILLI=$CHILLI/$DHCPIF
    HS_LANIF=$DHCPIF

    [ -f $CHILLI/config ] && . $CHILLI/config
}

MAIN_CONF=$CHILLI/main.conf
LOCAL_CONF=$CHILLI/local.conf
HS_CONF=$CHILLI/hs.conf
HS_TEMP=/tmp/hs.conf.$HS_LANIF
MAIN_TEMP=/tmp/main.conf.$HS_LANIF
CMDSOCK=$RUN_D/chilli.$HS_LANIF.sock
PIDFILE=$RUN_D/chilli.$HS_LANIF.pid
IPCFILE=chilli.$HS_LANIF.ipc

HS_UAMPORT=${HS_UAMPORT:-3990}
HS_RADIUS=${HS_RADIUS:-$HS_UAMSERVER}
HS_RADIUS=${HS_RADIUS:-localhost}
HS_RADSECRET=${HS_RADSECRET:-$HS_UAMSECRET}
HS_RADAUTH=${HS_RADAUTH:-1812}
HS_RADACCT=${HS_RADACCT=1813}
HS_ADMINUPDATEFILE=${HS_ADMINUPDATEFILE:-$LOCAL_CONF}
HS_ADMINTERVAL=${HS_ADMINTERVAL:-0}
HS_RADCONF=${HS_RADCONF:-off}
HS_RADCONF_SERVERS=${HS_RADCONF_SERVERS:+$(echo "$HS_RADCONF_SERVERS"|sed 's/[;, ]/ /g')}
HS_RADCONF_AUTHPORT=${HS_RADCONF_AUTHPORT:-1812}
HS_RADCONF_ACCTPORT=${HS_RADCONF_ACCTPORT:-1813}
HS_DNS_DOMAIN=${HS_DNS_DOMAIN:-lan}
HS_MACAUTHMODE=${HS_MACAUTHMODE:-off}
HS_USELOCALUSERS=${HS_USELOCALUSERS:-off}
HS_OPENIDAUTH=${HS_OPENIDAUTH:-off}
HS_ACCTUPDATE=${HS_ACCTUPDATE:-off}
HS_WISPRLOGIN=${HS_WISPRLOGIN:-$HS_UAMSERVICE}
HS_PAP_OK=${HS_PAP_OK:-on}
HS_DNS1=${HS_DNS1:-$HS_DNS}
HS_DNS1=${HS_DNS1:-$(grep '^nameserver' /etc/resolv.conf | head -n1 | awk '{print $2}')}
if [ $(uname) = "Linux" ]; then
HS_WANIF=${HS_WANIF:-$(route -n|grep '^0.0.0.0'|head -n1|awk '{print $8}')}
else
HS_WANIF=${HS_WANIF:-$(route get default | grep interface | awk '{print $2}')}
fi

bailout() { echo $1; exit; }

check_required() {
    [ -z "$HS_MODE" ]  && bailout "HS_MODE is required"
}

configs1=/tmp/configs1.$$
addconfig1() { [ -n "$*" ] && cat<<EOF>>$configs1
$*
EOF
}
configs2=/tmp/configs2.$$
addconfig2() { [ -n "$*" ] && cat<<EOF>>$configs2
$*
EOF
}

writeconfig1() {
    cat <<EOF
# THIS FILE IS AUTOMATICALLY GENERATED
cmdsocket       $CMDSOCK
unixipc         $IPCFILE
pidfile         $PIDFILE
net		$HS_NETWORK/$HS_NETMASK
uamlisten	$HS_UAMLISTEN
uamport         $HS_UAMPORT
dhcpif		$HS_LANIF
uamallowed	"$HS_UAMSERVER$webadmin$uamallow"
uamanydns
$(cat $configs1)
$HS_RAW_CONFIG1
EOF
}

writeconfig2() {
    cat <<EOF
radiusserver1	"$HS_RADIUS"
radiusserver2	"${HS_RADIUS2:-$HS_RADIUS}"
radiussecret	"$HS_RADSECRET"
radiusauthport  ${HS_RADAUTH:-1812}
radiusacctport  ${HS_RADACCT:-1813}
uamserver	"$(eval echo $HS_UAMFORMAT)"
radiusnasid	"${HS_NASID:-nas01}"
$(cat $configs2)
$HS_RAW_CONFIG2
EOF
}

writeconfig() {
    [ -e $LOCAL_CONF ] || touch $LOCAL_CONF
    [ -e $HS_CONF ] || touch $HS_CONF
    [ "$HS_USETAP" = "on" ] && addconfig1 "usetap"
    [ "$HS_NOARPENTRIES" = "on" ] && addconfig1 "noarpentries"
    [ "$HS_ANYIP" = "on" ] && addconfig1 "uamanyip"
    [ "$HS_NATANYIP" = "on" ] && addconfig1 "uamnatanyip"
    [ "$HS_NOC2C" = "on" ] && addconfig1 "noc2c"
    [ "$HS_REDIR" = "on" ] && addconfig2 "redir"
    [ "$HS_REDIRDNSREQ" = "on" ] && addconfig2 "redirdnsreq"

    [ "$HS_LAYER3" = "on" ] && addconfig1 "layer3"
    addconfig1 ${HS_LEASE:+"lease \"$HS_LEASE\""}

    [ "$HS_USER" != "" -a "$HS_UID" = "" ] && HS_UID=$(id -u $HS_USER)
    [ "$HS_USER" != "" -a "$HS_GID" = "" ] && HS_GID=$(id -g $HS_USER)

    addconfig1 ${HS_UID:+"uid \"$HS_UID\""}
    addconfig1 ${HS_GID:+"gid \"$HS_GID\""}

    [ -n "$HS_DHCPGATEWAY" ] && {
	if [ $(uname) = "Linux" ]; then
	HS_DHCPRELAYAGENT=${HS_DHCPRELAYAGENT:-$(ifconfig $(route -n|grep '^0.0.0.0'| \
	awk '{ print $8 }')|grep 'inet addr:'|cut -d: -f 2|cut -d' ' -f1)}
	else
	HS_DHCPRELAYAGENT=${HS_DHCPRELAYAGENT:-$(ifconfig $(netstat -rn | grep 'default' | \
	head -n1 | awk '{print$7}') | grep 'inet ' | cut -d/ -f 1 | cut -d' ' -f2)}
	fi
	addconfig1 "dhcpgateway \"$HS_DHCPGATEWAY\""
	addconfig1 "dhcprelayagent \"$HS_DHCPRELAYAGENT\""
    }

    addconfig1 ${HS_KNAME:+"kname \"$HS_KNAME\""}
    addconfig1 ${HS_DHCPLISTEN:+"dhcplisten \"$HS_DHCPLISTEN\""}
    addconfig1 ${HS_TUNDEV:+"tundev \"$HS_TUNDEV\""}
    addconfig1 ${HS_DYNIP:+"dynip $HS_DYNIP/${HS_DYNIP_MASK:-255.255.255.0}"}
    addconfig1 ${HS_STATIP:+"statip $HS_STATIP/${HS_STATIP_MASK:-255.255.255.0}"}
    addconfig1 ${HS_SSID:+"ssid \"$HS_SSID\""}
    addconfig1 ${HS_VLAN:+"vlan \"$HS_VLAN\""}
    addconfig1 ${HS_NASIP:+"nasip \"$HS_NASIP\""}
    addconfig1 ${HS_NASMAC:+"nasmac \"$HS_NASMAC\""}
    addconfig1 ${HS_DHCPMAC:+"dhcpmac \"$HS_DHCPMAC\""}
    addconfig1 ${HS_DNS_DOMAIN:+"domain \"$HS_DNS_DOMAIN\""}
    addconfig1 ${HS_DNS1:+"dns1 \"$HS_DNS1\""}
    addconfig1 ${HS_DNS2:+"dns2 \"$HS_DNS2\""}
    addconfig1 ${HS_TCPMSS:+"tcpmss \"$HS_TCPMSS\""}
    addconfig1 ${HS_DHCPOPT:+"dhcpopt \"$HS_DHCPOPT\""}

    [ "$HS_LOCATIONOPT82" = "on" ] && addconfig1 "locationopt82"
    [ "$HS_UAMHOMEPAGE" = "none" ] && HS_UAMHOMEPAGE=
    addconfig1 ${HS_UAMHOMEPAGE:+"uamhomepage $(eval echo $HS_UAMHOMEPAGE)"}
    addconfig1 ${HS_WISPRLOGIN:+"wisprlogin $HS_WISPRLOGIN"}
    addconfig1 ${HS_WWWDIR:+"wwwdir $HS_WWWDIR"}
    addconfig1 ${HS_WWWBIN:+"wwwbin $HS_WWWBIN"}
    addconfig1 ${HS_UAMUIPORT:+"uamuiport $HS_UAMUIPORT"}
    addconfig1 ${HS_ADMUSR:+"adminuser \"$HS_ADMUSR\""}
    addconfig1 ${HS_ADMPWD:+"adminpasswd \"$HS_ADMPWD\""}
    addconfig1 ${HS_CONUP:+"conup \"$HS_CONUP\""}
    addconfig1 ${HS_CONDOWN:+"condown \"$HS_CONDOWN\""}
    addconfig1 ${HS_MACUP:+"macup \"$HS_MACUP\""}
    addconfig1 ${HS_MACDOWN:+"macdown \"$HS_MACDOWN\""}

    [ -n "$HS_UAMDOMAINS" ] && {
	HS_UAMDOMAINS=$(echo $HS_UAMDOMAINS|sed 's/,/ /g')
	for s in $HS_UAMDOMAINS; do
	    addconfig1 "uamdomain $s"
	done
    }

    [ "$HS_AAA" = "http" ] && [ -n "$HS_UAMAAAURL" ] && {
	HS_RADIUS=localhost
	HS_RADIUS2=localhost
	HS_RADAUTH=1812
	HS_RADACCT=1813
	addconfig2 "uamaaaurl \"$HS_UAMAAAURL\""
    }

    HS_MACALLOW=$(echo "$HS_MACALLOW"|sed 's/ /,/g'|sed 's/,,/,/g'|sed 's/[:-]//g')
    addconfig1 ${HS_MACALLOW:+"macallowed $HS_MACALLOW"}

    HS_UAMALLOW=$(echo $HS_UAMALLOW|sed 's/ /,/g')
    uamallow=${HS_UAMALLOW:+",$HS_UAMALLOW"}

    HS_IPSRCALLOWED=$(echo $HS_IPSRCALLOWED|sed 's/ /,/g')
    addconfig1 ${HS_IPSRCALLOWED:+"ipsrcallowed $HS_IPSRCALLOWED"}

    addconfig1 ${HS_MAXCLIENTS:+"maxclients $HS_MAXCLIENTS"}
    addconfig1 ${HS_RADIUSQSIZE:+"radiusqsize $HS_RADIUSQSIZE"}
    addconfig1 ${HS_DHCPHASHSIZE:+"dhcphashsize $HS_DHCPHASHSIZE"}

    [ "$HS_NOWISPR1" = "on" ] || [ "$HS_NOWISPR1" = "true" ] && addconfig1 "nowispr1"
    [ "$HS_NOWISPR2" = "on" ] || [ "$HS_NOWISPR2" = "true" ] && addconfig1 "nowispr2"
    [ "$HS_WEB_ADMIN" = "http"  ] || [ "$HS_WEB_ADMIN" = "both" ] && webadmin="$webadmin,$HS_UAMLISTEN:80"
    [ "$HS_WEB_ADMIN" = "https" ] || [ "$HS_WEB_ADMIN" = "both" ] && webadmin="$webadmin,$HS_UAMLISTEN:443"
    [ "$HS_MACAUTHMODE" = "local" ] || [ "$HS_MACALLOWLOCAL" = "on" ] && addconfig1 "macallowlocal"
    [ "$HS_LOCAL" = "on" ] && webadmin="$webadmin,$HS_UAMLISTEN:$HS_LOCAL_PORT"

    [ "$HS_USELOCALUSERS" = "on" ] && {
	HS_LOCALUSERS=${HS_LOCALUSERS:-$CHILLI/localusers}
	touch $HS_LOCALUSERS
	addconfig1 "localusers $HS_LOCALUSERS"
    }

    [ -n "$HS_LOC_NAME" ] && {
	loc_name=$(echo "$HS_LOC_NAME" | sed 's/"//g')
	addconfig1 "locationname \"$loc_name\""
	isocc=$(echo    "$HS_LOC_ISOCC"  | sed 's/[^a-zA-Z]//g')
	cc=$(echo       "$HS_LOC_CC"     | sed 's/[^0-9]//g')
	ac=$(echo       "$HS_LOC_AC"     | sed 's/[^0-9]//g')
	network=$(echo  "$HS_LOC_NETWORK"| sed 's/[^a-zA-Z0-9]/_/g')
	provider=$(echo "$HS_PROVIDER"   | sed 's/[^a-zA-Z0-9]/_/g')
	[ -n "$provider" ] && provider="$provider,"
	[ -n "$HS_SSID" ] && {
	    [ -n "$network" ] && network="${network}_"
	    network="$network$HS_SSID"
	}
	loc_name=$(echo "$HS_LOC_NAME"  | sed 's/[^a-zA-Z0-9]/_/g')
	loc_id="isocc=$isocc,cc=$cc,ac=$ac,network=$provider$network"
	addconfig1 "radiuslocationname \"$loc_name\""
	addconfig1 "radiuslocationid \"$loc_id\""
    }

    # Application walled garden entries:
    [ "$HS_USE_MAP" = "on" ] && addconfig1 "uamdomain .google.com"

    writeconfig1 > $MAIN_TEMP

    # Not using auto-config, so set hs.conf settings directly
    if [ "$HS_RADCONF" != "on" -a "$HS_RADCONF" != "url" ]; then
	[ "$HS_PAP_OK" = "on" ] && addconfig2 "papalwaysok"
	[ "$HS_MACAUTH" = "on" ] && addconfig2 "macauth"
	[ "$HS_MACAUTH" = "on" -a -n "$HS_MACPASSWD" ] && addconfig2 "macpasswd \"$HS_MACPASSWD\""
	[ "$HS_MACAUTH" = "on" -a -n "$HS_MACSUFFIX" ] && addconfig2 "macsuffix \"$HS_MACSUFFIX\""
	[ "$HS_MACREAUTH" = "on" ] && addconfig2 "macreauth"
	[ "$HS_MACAUTHDENY" = "on" ] && addconfig2 "macauthdeny"
	[ "$HS_WPAGUESTS" = "on" ] && addconfig2 "wpaguests"
	[ "$HS_OPENIDAUTH" = "on" ] && addconfig2 "openidauth"
	[ "$HS_ACCTUPDATE" = "on" ] && addconfig2 "acctupdate"
	[ "$HS_DNSPARANOIA" = "on" ] && addconfig2 "dnsparanoia"
	[ "$HS_UAMALLOWPOST" = "on" ] && addconfig2 "uamallowpost"
	[ "$HS_IEEE8021Q" = "on" ] && addconfig2 "ieee8021q"
	[ "$HS_UAMUISSL" = "on" ] && addconfig2 "uamuissl"
	[ "$HS_REDIRSSL" = "on" ] && addconfig2 "redirssl"
	[ "$HS_DHCPRADIUS" = "on" ] && addconfig2 "dhcpradius"
	[ "$HS_RADIUSORIGINALURL" = "on" ] && addconfig2 "radiusoriginalurl"
	[ "$HS_SWAPOCTETS" = "on" ] && addconfig2 "swapoctets"
	[ "$HS_DOMAINDNSLOCAL" = "on" ] && addconfig2 "domaindnslocal"
	[ "$HS_SESKEEPALIVE" = "on" ] && addconfig2 "seskeepalive"
	[ "$HS_RADSEC" = "on" ] && addconfig2 "radsec"
	[ -n "$HS_USESTATUSFILE" ] && addconfig2 "usestatusfile \"$HS_USESTATUSFILE\""
	[ -n "$HS_UAMLOGOUTIP" ] && addconfig2 "uamlogoutip \"$HS_UAMLOGOUTIP\""
	[ -n "$HS_UAMALIASIP" ] && addconfig2 "uamaliasip \"$HS_UAMALIASIP\""
	[ -n "$HS_UAMALIASNAME" ] && addconfig2 "uamaliasname \"$HS_UAMALIASNAME\""
	[ -n "$HS_ADMINUPDATEFILE" ] && addconfig2 "adminupdatefile \"$HS_ADMINUPDATEFILE\""
	[ -n "$HS_UAMSECRET" ] && addconfig2 "uamsecret \"$HS_UAMSECRET\""
	[ -n "$HS_INJECT" ] && addconfig2 "inject \"$HS_INJECT\""
	[ -n "$HS_INJECTEXT" ] && addconfig2 "injectext \"$HS_INJECTEXT\""

	test ${HS_DEFSESSIONTIMEOUT:-0} -gt 0 && addconfig2 "defsessiontimeout $HS_DEFSESSIONTIMEOUT"
	test ${HS_DEFIDLETIMEOUT:-0} -gt 0 && addconfig2 "defidletimeout $HS_DEFIDLETIMEOUT"
	test ${HS_CHALLENGETIMEOUT:-0} -gt 0 && addconfig2 "challengetimeout $HS_CHALLENGETIMEOUT"
	test ${HS_CHALLENGETIMEOUT2:-0} -gt 0 && addconfig2 "challengetimeout2 $HS_CHALLENGETIMEOUT2"
	test ${HS_DEFBANDWIDTHMAXDOWN:-0} -gt 0 && addconfig2 "defbandwidthmaxdown $HS_DEFBANDWIDTHMAXDOWN"
	test ${HS_DEFBANDWIDTHMAXUP:-0} -gt 0 && addconfig2 "defbandwidthmaxup $HS_DEFBANDWIDTHMAXUP"
	test ${HS_DEFINTERIMINTERVAL:-0} -gt 0 && addconfig2 "definteriminterval $HS_DEFINTERIMINTERVAL"
	test ${HS_COAPORT:-0} -gt 0 && addconfig2 "coaport $HS_COAPORT"

	[ -n "$HS_SSLKEYFILE" -a -n "$HS_SSLCERTFILE" ] && {
	    addconfig2 "sslkeyfile $HS_SSLKEYFILE"
	    addconfig2 "sslcertfile $HS_SSLCERTFILE"
	}

	[ -n "$HS_SSLCAFILE" ] && addconfig2 "sslcafile $HS_SSLCAFILE"

	[ -n "$HS_POSTAUTH_PROXY" -a -n "$HS_POSTAUTH_PROXYPORT" ] && {
	    addconfig2 "postauthproxy $HS_POSTAUTH_PROXY"
	    addconfig2 "postauthproxyport $HS_POSTAUTH_PROXYPORT"
	}

	[ "$HS_RADPROXY" = "on" ] && {
	    addconfig2 "proxylisten ${HS_RADPROXY_LISTEN:-127.0.0.1}"
	    addconfig2 "proxyclient ${HS_RADPROXY_CLIENT:-127.0.0.1}"
	    addconfig2 "proxyport ${HS_RADPROXY_PORT:-1645}"
	    addconfig2 "proxysecret \"${HS_RADPROXY_SECRET:-$HS_RADSECRET}\""
	    [ "$HS_RADPROXY_MACACCEPT" = "on" ] && addconfig2 "proxymacaccept"
	    [ -n "$HS_RADPROXY_LOCATTR" ] && {
		HS_RADPROXY_LOCATTR=$(echo "$HS_RADPROXY_LOCATTR"|sed 's/|/ /g')
		for s in $HS_RADPROXY_LOCATTR; do
		    addconfig2 "proxylocattr \"$s\""
		done
	    }
	}

	# these are settings you would typically get from a centralized source
	# but, if not, they are also just configurable normally. a better way is needed
	# to manage settings and ensure they are not repeated

	if [ "$HS_CONF_INONE" = "1" ]; then
	    writeconfig2 >> $MAIN_TEMP
	else
	    writeconfig2 > $HS_TEMP
	fi
    fi

    touch $MAIN_TEMP $HS_TEMP
    update_new_file $MAIN_TEMP $MAIN_CONF
    update_new_file $HS_TEMP $HS_CONF
    rm -f $configs1 $configs2
}

files_equal() {    # returns 0 for equal, 1 for not-equal
    [ -x /usr/bin/cmp ] || [ -x /bin/cmp ] && {
	cmp -s $1 $2 && return 0;
	return 1;
    }
    [ -x /usr/bin/md5sum ] || [ -x /bin/md5sum ] && {
	[ "$(md5sum $1 | cut -f1 -d' ')" = "$(md5sum $2 | cut -f1 -d' ')" ] && return 0;
	return 1;
    }
    [ -x /usr/bin/md5 ] || [ -x /sbin/md5 ] || [ -x /bin/md5 ] && {
	[ "$(md5 $1)" = "$(md5 $2)" ] && return 0;
	return 1;
    }
    return 0;
}

update_new_file() {
    files_equal $1 $2 || {
	cp -f $1 $2
	return 0;
    }
    return 1;
}

checkfornew() {
    update_new_file $HS_TEMP $HS_CONF && {
	killall -HUP chilli 2>/dev/null >/dev/null
    }
}

radiusconfig() {
    [ -e $LOCAL_CONF ] || touch $LOCAL_CONF
    [ -e $HS_CONF ] || touch $HS_CONF
    if [ "$HS_RADCONF" = "url" ]; then
	for s in $HS_RADCONF_URL $HS_RADCONF_URLS; do
	    sep='?'
	    opt=
	    qs="config=chilli&mac=$HS_NASMAC&nasid=$HS_NASID&nasip=$HS_NASIP&ssid=$HS_SSID"
	    [ "$s" = "$(echo $s|awk -F'?' '{ print $1 }')" ] || sep='&'
	    [ "$HS_RADCONF_USER" = "" ] || opt="-u '$HS_RADCONF_USER:$HS_RADCONF_PWD'"
	    curl -k -A CoovaAP $opt "$s$sep$qs" 2>/dev/null > $HS_TEMP && break;
	done
    elif [ "$HS_RADCONF" = "on" ]; then
	for s in $HS_RADCONF_SERVER $HS_RADCONF_SERVERS; do
	    $SBIN/chilli_radconfig \
		--radiustimeout=30 \
		--radiusretry=3 \
		--radiusretrysec=3 \
		--radiusserver1="$s" \
		--radiussecret="$HS_RADCONF_SECRET" \
		--radiusauthport="$HS_RADCONF_AUTHPORT" \
		--radiusacctport="$HS_RADCONF_ACCTPORT" \
		--nasip="$HS_NASIP" \
		--nasmac="$HS_NASMAC" \
		--adminuser="$HS_RADCONF_USER" \
		--adminpasswd="$HS_RADCONF_PWD" \
		> $HS_TEMP && break;
	done
#    elif [ "$HS_LOCAL" != "on" ]; then
#	$SBIN/chilli_radconfig > $HS_TEMP && { checkfornew; break; }
    fi
    checkfornew
}

