Thursday, September 9, 2010

wircon-0.0.1-1 -- a wireless detection/connection script for broadcom 43** wireless cards

I wrote this because none of the available programs seem to handle the Broadcom 43** wireless cards very well. The script has a couple of options. It can be sent a pre-determined network nickname to connect to, or it can read from a list of "preferred networks" and connect to whichever it finds first. It also contains a silent (-s) switch, which removes all output. The network nickname is what's passed to the script when called, so with wircon home, once the script reached the "set_network" function, it would set the ESSID corresponding to 'home'. This way one doesn't have to type out 'FooBar_G_Serial_0834DS90' everytime they want to connect to that network. However, the preferred networks file 'pref_networks.lst' should contain the actual network ESSID.
The script has been completely modularized, so it's run as a series of functions. It's also meant to be backgrounded as it will switch to a function which loops infinitely, checking the internet connection with each iteration; if none is found, it calls the main connection cycle again and repeats. If it is unable to connect after 5 tries, it exits completely with an errorcode of 1.

#!/bin/sh

dhcpcdPID="/var/run/dhcpcd.pid"
networks=`cat /home/jason/devel/scripts/wircon/pref_networks.lst`

# make sure the script is being run as root
if [[ $(id -u) != "0" ]]; then
    echo "This script must be run as root"
    exit 1
fi

# scan for essids located in pref_networks.lst
find_network() {
  for i in $networks; do
    iwlist wlan0 scan | grep $i &> /dev/null
    if [[ "$?" = "0" ]]; then
      local essid=$i
      break
    fi
  done

  case $essid in
    "[Network_ESSID1")
    network="NE1"
    ;;
    "[Network_ESSID2")
    network="NE2"
    ;;
    "Network_ESSID3")
    network="NE3"
  esac
}

# if dhcpcd is running, stop it
do_dhcpcd_check() {
  if [[ -f $dhcpcdPID ]]; then
    if [[ $silent = "1" ]]; then
      dhcpcd -x
    else
      dhcpcd -x -q
    fi
  fi

}

# load wireless firmware
do_load_firmware() {
  [[ $silent = "1" ]] && echo "loading wireless firmware"
  ifconfig wlan0 up
}

# set essid and, if applicable, network key
do_set_network() {
  [[ $silent = "1" ]] && echo "setting network parameters"
  iwconfig wlan0 essid $ESSID
  if [[ $KEY != "" ]]; then
      iwconfig wlan0 key $KEY
  fi
}

# try for dhcp lease
do_dhcpcd() {
  if [[ $silent = "1" ]]; then
    dhcpcd
  else
    dhcpcd -q
  fi
}

# something that helps find a carrier
do_channel_auto() {
  [[ $silent = "1" ]] && echo "connecting to carrier"
  iwconfig wlan0 channel auto
}

# make sure it worked
check_connection() {
  ping -c 1 www.google.com &> /dev/null

  if [[ $? = "0" ]]; then
    return 0
  else
    return 1
  fi
}

# set the desired network
set_network() {
  case $network in
    "NE1")
    ESSID="[Network_ESSID1]"
    KEY="biglongkey"
    ;;
    "NE2")
    ESSID="[Network_ESSID2]"
    KEY="hopefullydifferentbiglongkey"
    ;;
    "NE3")
    ESSID="[Network_ESSID3]"
        # unsecure network
    KEY=
    ;;
    *)
    [[ $silent = "1" ]] && echo "$1 is not a recognized essid"
  esac
}

connection_monitor() {
  while [[ 1 = 1 ]]; do
    sleep 10
    check_connection
    if [[ $? = 1 ]]; then
      main
    fi
  done
}

main() {
  count=0
  while [[ $count < 5 ]]; do
    do_dhcpcd_check
    do_load_firmware
    do_set_network
    sleep 2
    do_dhcpcd
    do_channel_auto
    check_connection
    if [[ $? = 0 ]]; then
      [[ $silent = "1" ]] && echo "connection established"
      connection_monitor
    else
      let count=$count+1
    fi
  done
}

# check scripts usage
silent=1
if [[ $# > 0 ]]; then
  if [[ $1 = "-s" ]]; then
    silent=0
    shift
  fi
  if [[ ! -z $1 ]]; then
    network=$1
  else
    find_network
  fi
else
  find_network
fi

set_network

main

exit 1

No comments:

Post a Comment