#!/bin/bash
#This script will attempt dhcp on nics in the order they appear in 'ifconfig -a'
#on the wifi nics only trough wpa_supplicant
#The script will exit after the first successful IP addr is aquired
#This version does not require iw or wireless_tools, just working dhcpcd,wpa_supplicant and wpa_cli
#and will setup the system clock via ntpdate on raspberry pi
Name="$(basename $0)"
NicList="$(ifconfig  -a | awk -F: '$1~/^e|^w/ {printf("%s ", $1)}')"
Reg=JP
Wcfg=/etc/wpa_supplicant.conf
Timeout="20 second"
NTPServer=pool.ntp.org

get_known_essids ()
{ grep ssid= /etc/wpa_supplicant.conf |awk -v FS=\" '
  $1 ~ /^#/ {next}
  NR == 1 {printf("%s",$2)}
  NR > 1 {printf("|%s",$2)}
  END {printf("\n")}
  '
}

get_ap_list ()
{ wpa_cli <<< "scan" >/dev/null 2>&1
  sleep 4
  wpa_cli <<< "scan_results" | sed '1,/^bssid/d; s/[ |\t]\+/ /g; s/^.*\[ESS\]//; s/^ *//'
}

nic_stat ()
{ cat /sys/class/net/${1}/operstate
}

nic_carrier ()
{  cat /sys/class/net/${1}/carrier
}

is_wireless ()
{ [ -d /sys/class/net/${1}/wireless ] && return 0 || return 1
}

start_wired ()
{ if nic_stat $1 | grep -qi down
  then
    echo -n "$1 is down: bringing up ..."
    ifconfig $1 up >/dev/null 2>&1
    sleep 3
  else
    echo -n "$1 is up ..."
  fi
  if [ $(nic_carrier $1) -eq 0 ]
  then
    echo " not linked"
    ifconfig $1 down
  else
    echo " linked"
    dhcpcd -q -L -t 10 -h $(hostname) $1 && ifconfig $1 | awk '$1 ~ /inet/ {print $2}' || return 0
    grep -qi raspberry /proc/device-tree/model 2>/dev/null && ntpdate -b $NTPServer
    exit 0
  fi
}

wiif_down ()
{ dhcpcd -k $1
  PID=$(ps -ef |grep -v grep |grep wpa_supplicant |grep "i$1" |awk '{print $2}')
  [ "$PID" != "" ] && kill -9 $PID >/dev/null 2>&1
  ifconfig $1 down
}

if_down ()
{ dhcpcd -k $1
  ifconfig $1 down
}

wiif_up ()
{ wpa_cli <<< "reassociate" >/dev/null 2>&1
  Status=$(wpa_cli <<< "status" |awk -F= '$1~/wpa_state=*/ {print $2}')
  EndTime=$(date -d "now +${Timeout}" +%s)
  while [ "$Status" != "COMPLETED" -a $(date +%s)  -le $EndTime ]
  do
    sleep 0.3
    Status=$(wpa_cli <<< "status" |awk -F= '$1~/wpa_state=*/ {print $2}')
  done
  dhcpcd -q -t 10 -h $(hostname) $1 && ifconfig $1 | awk '$1 ~ /inet/ {print $2}' || return 0
  grep -qi raspberry /proc/device-tree/model 2>/dev/null && ntpdate -b $NTPServer
  exit 0
}

start_wireless ()
{ if nic_stat $1 | grep -qi down
  then
    echo -n "$1 is down: bringing up ..."
    ifconfig $1 up >/dev/null 2>&1
    sleep 2
    wpa_supplicant -B -W -Dwext -i$1 -c$Wcfg >/dev/null 2>&1 && sleep 0.2
  else
    echo -n "$1 is up ..."
  fi 
  APList="$(get_ap_list $1)"
  GrepString="$(get_known_essids)"
  if grep -qE "$GrepString" <<< "$APList" && [ "$GrepString" != "" ]
  then
    echo " know AP in range"
    wiif_up $1
  else
    echo " no know AP in range"
    ifconfig $1 down
    killall -9 wpa_supplicant
  fi  
}

do_start ()
{ Count=0
  for nic in $NicList
  do
    ifconfig  $nic | grep -qw inet && ((Count++))
  done

  [ $Count -gt 0 ] && exit
  for nic in $NicList
  do
    is_wireless $nic && Type=wireless || Type=wired
    
    if ifconfig  $nic | grep -qw inet
    then
      echo "$nic alredy up"
      exit 0
    else
      start_$Type $nic
    fi
  done
}

do_stop ()
{ for nic in $NicList
  do
    if ifconfig  $nic | grep -qw inet
    then
      echo "Stopping $nic"
      is_wireless $nic && Type=wi || Type=""
      ${Type}if_down $nic
    fi
  done
  killall -9 dhcpcd
  killall -9 wpa_supplicant
}

case ${1^^} in
  START) do_start ;;
  STOP) do_stop ;;
  RESTART) do_stop ; do_start ;;
  *) echo "What ? : $Name <start|stop|restart>"
esac
