#!/sbin/runscript
# Charlie's modified version /etc/init.d/eagle-usb
# should allow to have other ppp links up at the same time.
# should have got rid of the race condition which seemed to show when 
#   doing a restart

PPP=$(which pppd 2>/dev/null)
EAGLECTRL=$(which eaglectrl 2>/dev/null)
UMOUNT=$(which umount 2>/dev/null)
IFCONFIG=$(which ifconfig 2>/dev/null)
GREP=$(which grep 2>/dev/null)
LSMOD=$(which lsmod 2>/dev/null)
MAX_LOOP=160
EAGLESTAT=$(which eaglestat 2>/dev/null)
DHCPCD=$(which dhcpcd 2>/dev/null)
ROUTE=$(which route 2>/dev/null)
LOGGER=$(which logger 2>/dev/null)

LINKPIDFILE="/var/run/ppp-$LINKNAME.pid"  
# pipe output to $LOGGERCMD to either get it to go to logger or to /dev/null
LOGGERCMD="cat"
case "$DEBUG" in 
  YES|yes)
      [ -x ${LOGGER} ] && LOGGERCMD="${LOGGER} -t eagle-usb" 
      ;;
esac

check_pre_run () {
    # Check module is loaded
    (${LSMOD} | ${GREP} -q 'eagle.usb'); eend $? "Module eagle-usb is not loaded." || return 1

    # Check for eaglectrl
    [ -x ${EAGLECTRL} ] ; eend $? "Cannot find eaglectrl" || return 1

    # And showstat
    [ -x ${EAGLESTAT} ] ; eend $? "Cannot find eaglestat" || return 1        

    # And METHOD
    [ "${METHOD:-set}" != set ] ; eend $? "Please define METHOD in /etc/conf.d/eagle-usb" || return 1

    # And options
    [ "${OPTIONS:-set}" != set ] ; eend $? "Please define OPTIONS in /etc/conf.d/eagle-usb" || return 1
    [ -f ${OPTIONS} ] ; eend $? "Can't find OPTIONS file ${OPTIONS}" || return 1

    # And DSP
    [ "${DSP:-set}" != set ] ; eend $? "Please define DSP in /etc/conf.d/eagle-usb" || return 1
    [ -a ${DSP} ] ; eend $? "Can't find DSP file ${DSP}" || return 1

    # And synchro timeout
    [ "${SYNCHRO_TIMEOUT:-set}" != set ] ; eend $? "Please define SYNCHRO_TIMEOUT in /etc/conf.d/eagle-usb" || return 1

    # And linkname
    [ "${LINKNAME:-set}" != set ] ; eend $? "Please define LINKNAME=\"eagle\" in /etc/conf.d/eagle-usb" || return 1
    
    # Check usbdevfs is up and running  ?should we eend if mount fails?
    ( ${MOUNT} | ${GREP} -q usbdevfs) || ${MOUNT} none /proc/bus/usb -t usbdevfs >/dev/null 2>&1

    return 0
}


check_ppp () {

    # Check for PPP
    [ ! -z ${PPP} ] ; eend $? "failed to find ppp" || return 1

    # Check for /dev/ppp
    modprobe pppoe-generic &> /dev/null
    [ -c /dev/ppp ] || mknod /dev/ppp c 108 0 || eend $?  "Failed to create device /dev/ppp" || return 1

    # Check for PEER file
    [ "${PEER:-set}" != set ] ; eend $? "Please define \$PEER in /etc/conf.d/eagle-usb" || return 1
    [ -f /etc/ppp/peers/${PEER} ]  ; eend $? "Failed to find peer ${PEER} configuration" || return 1

    # Check for IFCONFIG
    [ -x ${IFCONFIG} ]; eend $? "Failed to find 'ifconfig'" || return 1
	 
}

check_dhcpcd () {

    # check for DHCPCD
    [ ! -z ${DHCPCD} ] ; eend $? "failed to find dhcpcd" || return 1
    
    # Check for IFCONFIG
    [ -x ${IFCONFIG} ]; eend $? "Failed to find 'ifconfig'" || return 1

    # Check for ROUTE
    [ -x ${ROUTE} ]; eend $? "Failed to find 'route'" || return 1

}

launch_pppd () {
    local RETURNED=1
    local LOOP=0

    echo "Starting Link $LINKNAME" | ${LOGGERCMD}  > /dev/null
    einfo "Launching PPP daemon ..."

    # Get interface name
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Set network interface
    ${IFCONFIG} ${EAGLE_IF} 192.168.60.30 netmask 255.255.255.0 up

    # have to use a pidfile as well as exec, so we can use pppd for other things
    # pppd will also give us a file containing both interface name and pid if we
    # use the linkname option
    start-stop-daemon --start --pidfile "$LINKPIDFILE"  --exec  ${PPP} call ${PEER} linkname $LINKNAME ${PPPDOPTS} | "$LOGGERCMD"  >/dev/null 2>&1

    # Wait for connection to be established
    while [ ${RETURNED} -ne 0 ] && [ ${LOOP} -le ${MAX_LOOP} ] ; do
	let LOOP=LOOP+1
	sleep 1
        #I'm not sure whether to do this every iteration, but it can't hurt...  
        find_eagle_pppif
        TMP=$?
	echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to start: $LOOP of $MAX_LOOP" |  ${LOGGERCMD} > /dev/null
        if [ $TMP  -eq  0 ] ;  then 
	  # echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to start"
          # shouldn't confuse ppp1 and ppp10
  	  ${IFCONFIG} | grep -q "${PPP_INTERFACE}[[:space:]]"
	  RETURNED=$? 
	fi
    done
    
    if [ ${LOOP} -gt ${MAX_LOOP} ] && [ ${RETURNED} -ne 0 ] ; then
	echo "Link $LINKNAME (${PPP_INTERFACE}) failed to start" |  ${LOGGERCMD}  > /dev/null
	return 1
    else
	echo "Link $LINKNAME (${PPP_INTERFACE}) started" |  ${LOGGERCMD}  > /dev/null
	return 0
    fi
}

stop_ppp () {

    local RETURNED=0
    local LOOP=0
    echo "Stopping Link $LINKNAME (${PPP_INTERFACE})" |   ${LOGGERCMD} > /dev/null
    find_eagle_pppif ;

    if [ -f $LINKPIDFILE ]
    then
	start-stop-daemon --stop --pidfile $LINKPIDFILE  pppd    

       # Wait for connection to go away
       find_eagle_pppif ;
       while [ ${RETURNED} -ne 1 ] && [ ${LOOP} -le ${MAX_LOOP} ] ; do
          let LOOP=LOOP+3
          sleep 1
	  echo "Waiting for link $LINKNAME (${PPP_INTERFACE}) to go away" |  ${LOGGERCMD}  > /dev/null
	  # could just use return value of find_eagle_pppif? 
	  # but then would have to check whether the interface exists 
          # and delete the pidfile if it doesn't? but then would have
          # a race condition?
  	  ${IFCONFIG} | grep -q "${PPP_INTERFACE}[[:space:]]"
          RETURNED=$?
       done
    
       if [ ${LOOP} -gt ${MAX_LOOP} ] && [ ${RETURNED} -ne 1 ] ; then
	   echo "Link $LINKNAME (${PPP_INTERFACE}) failed to stop" | ${LOGGERCMD}  > /dev/null
           return 1
       else
	   echo "Link $LINKNAME (${PPP_INTERFACE}) stopped" |  ${LOGGERCMD}  > /dev/null
           return 0
       fi
    else
      echo "File $LINKPIDFILE not found" |   ${LOGGERCMD} > /dev/null
      return 1
    fi
}


launch_dhcpcd () {
    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Launch dhcpcd
    start-stop-daemon --start --exec ${DHCPCD} -- ${DHCPCDOPTS} ${EAGLE_IF}  >/dev/null 2>&1

}


stop_dhcpd () {
    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Stop dhcpcd
    start-stop-daemon --stop --quiet --pidfile /var/run/dhcpcd-${EAGLE_IF}.pid


}

launch_static () {
    local RETURNED=1
    local LOOP=0

    einfo "Launching ADSL connexion..."

    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`
    
    # Set network interface
    ebegin "Bringing interface WAN (usb modem) (${EAGLE_IF}) up: ${STATIC_IP}/${STATIC_NM}"
    ${IFCONFIG} ${EAGLE_IF} ${STATIC_IP} netmask ${STATIC_NM} up
    eend $?

    # Setting default gateway
    ebegin "  Setting default gateway:${STATIC_GW} via inteface ${EAGLE_IF}"
    route add default gw ${STATIC_GW}
    eend $?
}

stop_static () {
    # Get interface
    export EAGLE_IF=`${EAGLECTRL} -i`

    # Bringing down interface
    ebegin "Bringing down interface WAN (usb modem) ${EAGLE_IF}"
    route del default
    eend $?
}



modem_is_operational () {
    # To be operational, firmware should be loaded. This mean, /proc/driver/eagle-usb
    # directory is not empty
    if ls /proc/driver/eagle-usb/* 1>/dev/null 2>&1
    then
	# Check "Modem is operational"
	${EAGLESTAT} | grep -q "Modem is operational"
    else
	return 1
    fi
}

load_and_sync () {
    # Load firmware /DSP/ etc only if the modem is not yet operational
    if modem_is_operational 
    then
	einfo "Modem already operational"
    else
	einfo "Loading firmware, DSP and trying to sync ..."
	${EAGLECTRL} -w -o${OPTIONS} -d${DSP} -s${SYNCHRO_TIMEOUT} | \
	                                          ${LOGGERCMD} 1>/dev/null 2>&1
    fi

    return $?
}

depend () {
    need modules logger
}


find_eagle_pppif()
{
   # identify which ppp interface is using the eagle.
   # returns zero for success, 1 if interface not found.
   PPP_INTERFACE=""
   #   LINKPIDFILE is defined at top of script-  "/var/run/ppp-${LINKNAME}.pid"
   # ppp kindly gives us both the PID and the interface name in the file 
   if [ -r "$LINKPIDFILE" ] ; then
       LINKPID=`grep -o -E '^[0-9]+'  "${LINKPIDFILE}"`
       PPP_INTERFACE=` grep -o -E '^ppp[0-9]+' "${LINKPIDFILE}"`
   fi
   if [ -z "$PPP_INTERFACE" ] ; then 
       return 1 ;
   else
       return 0 ;
   fi
}

    
start () {
    
    ebegin "Starting eagle-usb ..."
    
    # Check everything needed is in place
    check_pre_run ; eend $? "Pre-requesites check failed" || return 1

    # Let's try to upload firmware/dsp and do synchro
    load_and_sync ; eend $? "Failed to load or sync" || return 1

    case "${METHOD}" in 
	"pppoa")
           # launching ppp daemon
	    launch_pppd ; eend $? "Failed to start pppd daemon." || return 1
	    ;;
	"dhcpip")
	   # launching dhcpcd
	    launch_dhcpcd ; eend $? "Failed to start dhcpcd daemon." || return 1
	    ;;
	"staticip")
	    launch_static ; eend $? "Failed to start with static IP." || return 1
	    ;;
    esac

    # Cool .. we're plugged ..
    return 0
}
    
stop () {
    export EAGLE_IF=`${EAGLECTRL} -i`

    ebegin "Shutting down eagle-usb..."

    case "${METHOD}" in 
	"pppoa")
	    stop_ppp ; eend $? "Failed to stop 'pppd'"
	    ;;
	"dhcpip")
	    stop_dhcpd ; eend $? "Failed to stop 'dhcpcd'"
	    ;;
	"staticip")
	    stop_static ; eend $? "Failed to stop static IP." || return 1
	    ;;
    esac

    ${IFCONFIG} ${EAGLE_IF} down 1>/dev/null 2>&1


}
