#!/bin/sh

################################################################################
# Binary programs used by this script.                                         #
################################################################################
IFCONFIG=`which ifconfig`
WICONTROL=`which wicontrol`
DHCLIENT=`which dhclient`
NETSTAT=`which netstat`
ROUTE=`which route`
DIALOG=`which dialog`
KLDLOAD=`which kldload`
KLDUNLOAD=`which kldunload`

################################################################################
# The network device name and the location of run-time storage.                #
################################################################################
NETDEV="ndis0"
DB_DIR="/var/run/wireless"

################################################################################
# Some parameters used for the User Interface.                                 #
################################################################################
DLG_TITLE="Wireless Connection Manager"
DLG_DIMENSIONS="20 50"

################################################################################
# Management of the Wireless Network Device.                                   #
#                                                                              #
# There are four possible options to run this script, they are listed below    #
# and parsed as a command line option.  Finally, this script may ONLY be run   #
# as root, a regular user attempting to run this script will receive an error  #
# message.                                                                     #
################################################################################
if [ `id -u` -ne "0" ]; then
    echo "ERROR: You appear to be `id -un` but you need to run this script as root"
    exit 1
fi

################################################################################
# Create the run-time storage directory if it doesn't exist.                   #
################################################################################
mkdir -p $DB_DIR

################################################################################
# wireless.sh start                                                            #
#                                                                              #
# Called by the system during system start up.  We load the if_ndis kernel     #
# module that will create the ndis? device.  The device is created as being    #
# "down", it can be brough up by executing this script with the "connect"      #
# option.                                                                      #
################################################################################
case "$1" in
start)
    echo "Creating Wireless Network Device ($NETDEV)"
    $KLDLOAD if_ndis > /dev/null
	;;
    
################################################################################
# wireless.sh connect                                                          #
#                                                                              #
# The user wishes to bring up the wireless network device AND connect to a     #
# wireless network.  We do the following:                                      #
# - Enable the wireless network device ndis?                                   #
# - Obtain a list of available access points.                                  #
# - Display the list and allow the user to make a selection of which access    #
#   point to associate with.                                                   #
# - If there are no access points, or the user cancels the selection, bring    #
#   down the network device and exit.                                          #
# - Associate the network device to the selected Access Point.                 #
# - Backup the existing /etc/resolv.conf file so it can be restored later.     #
# - Backup existing default route information so that it be later restored.    #
# - Run dhclient on the network device to obtain an IP address and set basic   #
#   routing information.                                                       #
# - Get all routes from the route table associated with the wireless network   #
#   device and display them to the user.                                       #
################################################################################
connect)
    INFO="Bringing up Wireless network device - $NETDEV...\n"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
    $IFCONFIG $NETDEV up

    ############################################################################
    INFO="$INFO\nScanning for available connection points"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
    
    for NWID in `$WICONTROL -i $NETDEV -l | grep netname | awk '{print $4}' | sort | uniq`
    {
        MENULIST="$MENULIST $NWID Open_Wireless_Access_Point"
    }

    $DIALOG --title "$DLG_TITLE" \
            --menu "Please select the Access Point you would like to attach to:" \
            $DLG_DIMENSIONS 12 \
            $MENULIST \
            2> tempfile

    ############################################################################
    if [ $? -ne 0 ]; then
        $IFCONFIG $NETDEV down
        $DIALOG --title "$DLG_TITLE" \
                --msgbox "No connection established, application terminated." $DLG_DIMENSIONS
        exit 0
    fi
    ACCESS_POINT=`cat tempfile`

    ############################################################################
    INFO="Connecting to Access Point - $ACCESS_POINT\n"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
    $IFCONFIG $NETDEV nwid $ACCESS_POINT
    
    INFO="$INFO\n - Associated $NETDEV with $ACCESS_POINT"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS

    ############################################################################
    cp /etc/resolv.conf $DB_DIR/resolv.conf
    INFO="$INFO\n - Backed up /etc/resolv.conf"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS

    ############################################################################
    echo "default `route -n get default | awk '/gateway:/ { print $2 }'`" > $DB_DIR/def_route
    INFO="$INFO\n - Backed up route (`cat $DB_DIR/def_route`)"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
    
    ############################################################################
    $ROUTE delete default
    $DHCLIENT $NETDEV
    INFO="$INFO\n - DHCP negotiated on $NETDEV\n - Updating Routing table"
    $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
    
    ############################################################################
    INFO="$INFO\n\nNew routes added"
    INFO="$INFO\n`$NETSTAT -nrf inet | grep $NETDEV | awk '{ print $1, $2 }'`\n"
    INFO="$INFO\nConnected!  Press <Enter> to continue"
    $DIALOG --title "$DLG_TITLE" --msgbox "$INFO" $DLG_DIMENSIONS
    ;;
    
################################################################################
# wireless.sh hangup                                                           #
#                                                                              #
# - Kill the dhclient daemon running on the network device.                    #
# - Delete all routes associated with the wireless network device.             #
# - Restore the original default route.                                        #
# - Restore the original /etc/resolv.conf                                      #
# - Unload and then reload the if_ndis kernel module, this clears any settings #
#   from the current session that may impact on future settings.               #
################################################################################
hangup)
    INFO="Hanging up current wireless connection\n"

    if [ -e /var/run/dhclient.pid ]; then
        INFO="$INFO\n - Killing DHCP service"
        $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
        kill -9 `cat /var/run/dhclient.pid`
    fi
    
    ############################################################################
    if [ -s $DB_DIR/def_route ]; then
        INFO="$INFO\n - Restoring route (`cat $DB_DIR/def_route`)"
        $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
        $ROUTE delete default > /dev/null 2>&1
        $ROUTE add $(cat "$DB_DIR/def_route")
    fi
    
    ############################################################################
    if [ -e $DB_DIR/resolv.conf ]; then
        INFO="$INFO\n - Restoring /etc/resolv.conf"
        $DIALOG --title "$DLG_TITLE" --infobox "$INFO" $DLG_DIMENSIONS
        rm /etc/resolv.conf
        mv /$DB_DIR/resolv.conf /etc/resolv.conf
    fi
    
    ############################################################################
    rm -fR $DB_DIR/*
    
    ############################################################################
    /sbin/kldunload if_ndis
    ;;
    
################################################################################
# wireless.sh hangup                                                           #
#                                                                              #
# The system is going down, we need to restore some backed up information so   #
# that it is available the next time the system boots.  Routing tables are not #
# relevant and will be reset at next system boot time, however we need to:     #
# - Restore the original /etc/resolv.conf                                      #
# - Remove any database files from $DB_DIR                                     #
################################################################################
stop)
    if [ -e $DB_DIR/resolv.conf ]; then
        echo "Restoring pre-Wireless Network Device system configuration files..."
        rm /etc/resolv.conf
        mv $DB_DIR/resolv.conf /etc/resolv.conf
        rm -fR $DB_DIR/*
    fi
    ;;


################################################################################
# Default case, print usage information for the shell script.                  #
################################################################################
*)
	echo "Usage: `basename $0` {start|stop|connect|hangup}" >&2
	;;
esac

exit 0

