#!/bin/sh

RESOLVCONF="/tmp/resolv.conf"
NETCFGTMPDIR="/tmp/pmnetconfig"
DNSMASQSERVERCONF="${NETCFGTMPDIR}/dnsmasq.server.conf"

ECHO="echo"
LOG="echo"
RM="/bin/rm"
MKDIR="/bin/mkdir"
TOUCH="/bin/touch"
IPROUTE2="/sbin/ip"
IPTABLES="/usr/sbin/iptables"
IFCONFIG="/sbin/ifconfig"
STOP="/sbin/stop"
START="/sbin/start"
KILLALL="/usr/bin/killall"
SED="/bin/sed"
IPTABLESRESTORE="/usr/sbin/iptables-restore"

CMSTATICROUTEPATH="/etc/pmnetconfig/staticroutes"

CMCSCOTUNINTERFACENAME="cscotun0"
CMTUNNTERFACENAME="tun0"
CMWIFIINTERFACENAME="eth0"
CMUSBINTERFACENAME="usb0"
CMBTINTERFACENAME="bsl0"
CMBRINTERFACENAME="bridge0"
CMPPPINTERFACENAME0="ppp0"
CMPPPINTERFACENAME1="ppp1"
CMPPPINTERFACENAME2="ppp2"
CMRMNETINTERFACENAME0="rmnet0"
CMRMNETINTERFACENAME1="rmnet1"
CMRMNETINTERFACENAME2="rmnet2"

CMUSBDEFAULTGW="192.168.0.200"

CMSVCOTHER=0x00000000
CMSVCINTERNET=0x00000001

eval CMTBL_$CMCSCOTUNINTERFACENAME=100
eval CMTBL_$CMTUNNTERFACENAME=100
eval CMTBL_$CMWIFIINTERFACENAME=110
eval CMTBL_$CMUSBINTERFACENAME=120
eval CMTBL_$CMBTINTERFACENAME=130
eval CMTBL_$CMBRINTERFACENAME=130
eval CMTBL_$CMPPPINTERFACENAME0=200
eval CMTBL_$CMPPPINTERFACENAME1=201
eval CMTBL_$CMPPPINTERFACENAME2=202
eval CMTBL_$CMRMNETINTERFACENAME0=200
eval CMTBL_$CMRMNETINTERFACENAME1=201
eval CMTBL_$CMRMNETINTERFACENAME2=202

eval CMIFPRIO_$CMCSCOTUNINTERFACENAME=1
eval CMIFPRIO_$CMTUNNTERFACENAME=1
eval CMIFPRIO_$CMWIFIINTERFACENAME=2
eval CMIFPRIO_$CMPPPINTERFACENAME0=30
eval CMIFPRIO_$CMPPPINTERFACENAME1=31
eval CMIFPRIO_$CMPPPINTERFACENAME2=32
eval CMIFPRIO_$CMRMNETINTERFACENAME0=30
eval CMIFPRIO_$CMRMNETINTERFACENAME1=31
eval CMIFPRIO_$CMRMNETINTERFACENAME2=32
eval CMIFPRIO_$CMUSBINTERFACENAME=40
eval CMIFPRIO_$CMBTINTERFACENAME=50
eval CMIFPRIO_$CMBRINTERFACENAME=50


NetCfgExecInBackground() {
        ${LOG} "${*} >/dev/null 2>&1 &"
        ${*} >/dev/null 2>&1 &
}

NetCfgCalcTblNum() {
    eval CMTBLNUM="$"CMTBL_${1}
}

NetCfgCalcPrio() {
    eval CMIFPRIO="$"CMIFPRIO_${1}
}

NetCfgSetAddr() {
    ${LOG} "${IFCONFIG} ${CMINTERFACE} ${CMIPADDR} netmask ${CMNETMASK}"
    ${IFCONFIG} ${CMINTERFACE} ${CMIPADDR} netmask ${CMNETMASK}
}

NetCfgSetSrcRule() {
    ${LOG} "${IPROUTE2} rule add from ${1} table ${2}"
    ${IPROUTE2} rule add from ${1} table ${2}
}

NetCfgSetDstRule() {
    ${LOG} "${IPROUTE2} rule add to ${1} table ${2}"
    ${IPROUTE2} rule add to ${1} table ${2}
}

NetCfgSetLinkRoute() {
    ${LOG} "${IPROUTE2} route add ${1}/${2} dev ${3} proto kernel scope link src ${4} ${TBL} ${CMTCPWND}"
    ${IPROUTE2} route add ${1}/${2} dev ${3} proto kernel scope link src ${4} ${TBL} ${CMTCPWND}
}

NetCfgSetRoute() {
    while [ $1 ]; do
        if [ ${4} = "0.0.0.0" ]; then
            CMTMPROUTEGW=""
        else
            CMTMPROUTEGW="via ${4}"
        fi
        ${LOG} "${IPROUTE2} route add ${1}/${3} ${CMTMPROUTEGW} ${TBL} ${CMTCPWND}"
        ${IPROUTE2} route add ${1}/${3} ${CMTMPROUTEGW} ${TBL} ${CMTCPWND}
        shift
        shift
        shift
        shift
    done
}

NetCfgSetDefgw() {
    if [ $1 ]; then
        if [ ${1} = "0.0.0.0" ]; then
            CMTMPROUTEGW=""
        else
            CMTMPROUTEGW="via ${1}"
        fi
        CMDEFGWMETRIC=${CMIFPRIO}
        ${LOG} "${IPROUTE2} route add default ${CMTMPROUTEGW} dev ${CMINTERFACE} metric ${CMDEFGWMETRIC} ${TBL} ${CMTCPWND}"
        ${IPROUTE2} route add default ${CMTMPROUTEGW} dev ${CMINTERFACE} metric ${CMDEFGWMETRIC} ${TBL} ${CMTCPWND}
    fi
}

NetCfgSetDns() {
    if [ ! ${1} ]; then
        ${LOG} "No DNS servers"
        return
    fi

    if [ -f ${RESOLVCONF} ]; then
        CURRENTDNSPRIO=`grep Priority ${RESOLVCONF} | cut -d" " -f3`
        if [ ${CURRENTDNSPRIO} ]; then
            ${LOG} "Current Dns priority ${CURRENTDNSPRIO}"
        
            if [ ${CURRENTDNSPRIO} -lt ${CMIFPRIO} ]; then
                ${LOG} "Not overrwriting DNS"
                return
            fi
        fi
    fi

    ${ECHO} '# Autogenerated by PmNetConfigManager. DO NOT MODIFY!!' >${RESOLVCONF}
    ${ECHO} "# Interface ${CMINTERFACE}" >>${RESOLVCONF}
    ${ECHO} "# Priority ${CMIFPRIO}" >>${RESOLVCONF}

    while [ $1 ]; do
        ${LOG} "nameserver ${1}"
        ${ECHO} nameserver ${1} >>${RESOLVCONF}
        shift
    done
}

NetCfgSetDnsRules() {
    while [ $1 ]; do
        ${LOG} "${IPROUTE2} rule add to ${1} table ${CMTBLNUM}"
        ${IPROUTE2} rule add to ${1} table ${CMTBLNUM}
        shift
    done
}

NetCfgSetDnsServersForDomains() {
    if [ ! "${CMDNSDOMAINS}" ]; then
        ${LOG} "No specific domains for DNS"
        return
    fi

    if [ ! "${CMDNSSERVERS}" ]; then
        ${LOG} "No DNS servers for specific domains"
        return
    fi

    CMD="${ECHO} -e "

    for i in ${CMDNSDOMAINS}; do
        for j in ${CMDNSSERVERS}; do
            CMD="${CMD}server=/${i}/${j}\\\n"
        done
    done

    CMD="${CMD} >>${DNSMASQSERVERCONF}"
    
    ${LOG} "${CMD}"
    eval ${CMD}
}

NetCfgClearDns() {
    ${LOG} "${ECHO} # No DNS servers available. >${RESOLVCONF}"
    ${ECHO} "# No DNS servers available." >${RESOLVCONF}
}


# If we modified a dnsmasq conf file, then we need
# to restart dnsmasq so that it reads the changed
# conf file. If we only modified resolv.conf, then
# we only need send a HUP to dnsmasq so that it 
# re-reads resolv.conf.
NetCfgCommitDns() {
    if [ "${CMDNSSERVERS}" ]; then
        if [ "${CMDNSDOMAINS}" ]; then
            ${STOP} dnsmasq
            ${START} dnsmasq
            
            #have to add a delay to wait for dnsmasq to come up before going forward
			x=`dbus-send --print-reply --system  --type=method_call --dest='uk.org.thekelleys.dnsmasq'  /uk/org/thekelleys/dnsmasq uk.org.thekelleys.GetVersion`
			count=0
			
            while [ -z "$x" ] && [ "15" -gt "$count" ]
            do
              ${LOG} "Waiting for dnsmasq to come up"
              usleep 100000             
              let "count += 1"                                                                                                                                    
              x=`dbus-send --print-reply --system  --type=method_call --dest='uk.org.thekelleys.dnsmasq'  /uk/org/thekelleys/dnsmasq uk.org.thekelleys.GetVersion`
            done
                  
            if [ -z "$x" ] && [ "15" -gt "$count" ]                                          
            then                                                                    
              ${LOG} "Failed to detect dnsmasq"    
            else                          
              ${LOG} "dnsmasq is up"
            fi      
            
        else
            ${LOG} "${KILLALL} -HUP dnsmasq"
            ${KILLALL} -HUP dnsmasq
        fi
    fi
}

NetCfgCommitRoutes() {
    ${LOG} "${IPROUTE2} route flush cache"
    ${IPROUTE2} route flush cache
}

NetCfgCommit() {
    NetCfgCommitRoutes
    NetCfgCommitDns
}

NetCfgDelAddr() {
   ${LOG} "${IPROUTE2} addr del ${1}/${2} dev ${3}"  
   ${IPROUTE2} addr del ${1}/${2} dev ${3}  
}

NetCfgDelSrcRule() {
    ${LOG} "${IPROUTE2} rule del from ${1} table ${2}"
    ${IPROUTE2} rule del from ${1} table ${2}
}

NetCfgDelDstRule() {
    ${LOG} "${IPROUTE2} rule del to ${1} table ${2}"
    ${IPROUTE2} rule del to ${1} table ${2}
}

NetCfgDelRoute() {
    ${LOG} "${IPROUTE2} route flush ${TBL}"
    ${IPROUTE2} route flush ${TBL}
}

NetCfgDelDns() {
    if [ -f ${RESOLVCONF} ]; then
        CURRENTDNSINTF=`grep Interface ${RESOLVCONF} | cut -d" " -f3`
        if [ ${CURRENTDNSINTF} ]; then
            ${LOG} "Current Dns interface ${CURRENTDNSINTF}"
        
            if [ ${CURRENTDNSINTF} = ${CMINTERFACE} ]; then
                NetCfgClearDns
                
                if [ ${CMINTERFACENEXT} ]; then
                    ${LOG} "Restoring DNS to ${CMINTERFACENEXT}"
                    OLDINTF=${CMINTERFACE}
                    CMINTERFACE=${CMINTERFACENEXT}
                    NetCfgCalcPrio ${CMINTERFACE}
                    NetCfgSetDns $CMDNSSERVERSNEXT

                    CMINTERFACE=${OLDINTF}
                    NetCfgCalcPrio ${CMINTERFACE}
                fi
            fi
        fi
    fi
}

NetCfgDelDnsRules() {
    while [ $1 ]; do
        ${LOG} "${IPROUTE2} rule del to ${1} table ${CMTBLNUM}"
        ${IPROUTE2} rule del to ${1} table ${CMTBLNUM}
        shift
    done
}

NetCfgDelDnsServersForDomains() {
    if [ ! "${CMDNSDOMAINS}" ]; then
        ${LOG} "No specific domains for DNS"
        return
    fi

    if [ ! "${CMDNSSERVERS}" ]; then
        ${LOG} "No DNS servers for specific domains"
        return
    fi

    CMD="${SED} -i "

    for i in ${CMDNSDOMAINS}; do
        for j in ${CMDNSSERVERS}; do
            CMD="${CMD} -e `echo \'/\\\/${i}\\\/${j}\$/d\' | ${SED} 's/\./\\\\./g'`"
        done
    done

    CMD="${CMD} ${DNSMASQSERVERCONF}"

    ${LOG} "${CMD}"
    eval ${CMD}
}

NetCfgEvalStaticRoutes() {

    STATICROUTEFILES=`ls $CMSTATICROUTEPATH/ | grep .${1}`
    
    if [ ${2} = "0.0.0.0" ]; then
        CMTMPROUTEGW=""
        ${LOG} "No Static Routes over 0.0.0.0"
    else
    	CMTMPROUTEGW="via ${2}"
    
	    if [ "${STATICROUTEFILES}" ]; then
	    	for SRFILENM in ${STATICROUTEFILES}
	    	do
	    		FORCEDROUTEIP=`cut -d : -f 2 -s $CMSTATICROUTEPATH/$SRFILENM`
	    		FORCEDROUTEIP=${FORCEDROUTEIP//\"/}
	    		${LOG} "${IPROUTE2} route add ${FORCEDROUTEIP} ${CMTMPROUTEGW}"
	            ${IPROUTE2} route add ${FORCEDROUTEIP} ${CMTMPROUTEGW}
	    	done
	    fi
    fi    
}

NetCfgSetIpTableRules() {
	${IPTABLESRESTORE} < /etc/pmnetconfig/iptables-common.config
	if [[ -e /var/gadget/usbnet_enabled ]]; then
		exec /etc/pmnetconfig/iptables-usbnetmode.config
	fi	
}

