#!/bin/sh # /etc/rc.d/rc.wireless # $Id: rc.wireless,v 1.4 2006/08/15 13:09:01 eha Exp eha $ # # Wireless network card setup. # # This script sets up PCI, USB, and 32-bit Cardbus wireless devices # NOT 16-bit PCMCIA cards! Those are configured in /etc/pcmcia/. # Single parameter to this script is the name of a network interface. # Normally this script is called from rc.inet1 rather than run # directly. # # This script is a modified '/etc/pcmcia/wireless' script # 09/apr/2004 by Eric Hameleers # 16/sep/2004 * Eric Hameleers * Fixed iwspy and iwpriv commands # 08/apr/2005 * Eric Hameleers * Allow per-interface overrides of the wireless # parameters (see /etc/rc.d/rc.inet1.conf) # 11/apr/2005 * Eric Hameleers * Tune wpa_supplicant interactions. # 23/apr/2005 * Eric Hameleers * First configure card with iwconfig, # before starting wpa_supplicant # 27/apr/2005 * Eric Hameleers * Multiple 'iwpriv $INTERFACE set' commands. # 14/feb/2006 * Eric Hameleers * Better error messages; alternative way of # getting HWADDR; parametrized WPA_WAIT value. # Don't kill an already running wpa_supplicant. # 29/apr/2006 * Pat Volkerding * Reverted HWADDR change, since it relies on # a binary (macaddr) that is not built or # installed by default since it is not # compatible with all interfaces. # 15/aug/2006 * Eric Hameleers * Added missing "" around $ESSID, which broke # ESSIDs that contain a space character. # LOGGER=${LOGGER:-cat} if [ -z $IFNAME ] ; then echo "WARNING: The script 'rc.wireless' must be executed by 'rc.inet1'!" | $LOGGER echo " You should run the command \"/etc/rc.d/rc.inet1 _start\" yourself." | $LOGGER return 1 2> /dev/null || exit 1 fi INTERFACE=$1 # Find the path where wireless tools are installed for IWPATH in /usr/{bin,sbin} /usr/local/{bin,sbin} /sbin /bin ; do if [ -x $IWPATH/iwconfig ] ; then break ; fi done # The same for wpa_supplicant (needed for WPA support) for SUPPATH in /usr/{bin,sbin} /usr/local/{bin,sbin} /sbin /bin ; do if [ -x $SUPPATH/wpa_supplicant ] ; then break ; fi done # Set all desired settings through the wireless tools IWCOMMAND="$IWPATH/iwconfig ${INTERFACE}" IWPRIVCMD="$IWPATH/iwpriv ${INTERFACE}" IWSPYCMD="$IWPATH/iwspy ${INTERFACE}" IFCOMMAND="/sbin/ifconfig ${INTERFACE}" is_wireless_device () { [ -x $IWPATH/iwconfig ] || return 1 LC_ALL=C $IWPATH/iwconfig $1 2>&1 | \ grep -Eiq "no wireless extensions|no such device" || return 0 return 1 } ############### # EXIT POINTS # ############### # Is the device wireless? If not, exit this script. is_wireless_device ${INTERFACE} || return 0 2> /dev/null || exit 0 # If we stop a wireless interface using wpa_supplicant, # we'll kill its wpa_supplicant daemon too and exit this script: if [ "$2" = "stop" ]; then WPAPID=`echo \`ps axww|grep wpa_supplicant |grep i${INTERFACE}\` |cut -f1 -d' '` [ ${WPAPID} ] && kill ${WPAPID} return 0 fi # ----------------------------------------------------- # Continue with the script - bringing the interface UP. # ----------------------------------------------------- # Bring interface up - for determining the HWADDR $IFCOMMAND up sleep 2 # Get the MAC address for the interface HWADDR=`/sbin/ifconfig ${INTERFACE} | sed -ne 's/.*\(..:..:..:..:..:..\).*/\1/p'` # Read the configuration information for the card with address $HWADDR # from /etc/rc.d/rc.wireless.conf: . /etc/rc.d/rc.wireless.conf # Let any per-interface overrides (the WLAN_xxxx parameters) that are set # in /etc/rc.d/rc.inet1.conf have precedence. # The reason: you might have multiple wireless cards of the same brand, or # connecting to multiple networks. # Position 'i' of this interface in the IFNAME array was determined in rc.inet1 CHANNEL=${WLAN_CHANNEL[$i]:-${CHANNEL}} ESSID=${WLAN_ESSID[$i]:-${ESSID}} FREQ=${WLAN_FREQ[$i]:-${FREQ}} FRAG=${WLAN_FRAG[$i]:-${FRAG}} IWCONFIG=${WLAN_IWCONFIG[$i]:-${IWCONFIG}} IWPRIV=${WLAN_IWPRIV[$i]:-${IWPRIV}} IWSPY=${WLAN_IWSPY[$i]:-${IWSPY}} KEY=${WLAN_KEY[$i]:-${KEY}} MODE=${WLAN_MODE[$i]:-${MODE}} NICKNAME=${WLAN_NICKNAME[$i]:-${NICKNAME}} NWID=${WLAN_NWID[$i]:-${NWID}} RATE=${WLAN_RATE[$i]:-${RATE}} RTS=${WLAN_RTS[$i]:-${RTS}} SENS=${WLAN_SENS[$i]:-${SENS}} WPA=${WLAN_WPA[$i]:-${WPA}} WPADRIVER=${WLAN_WPADRIVER[$i]:-${WPADRIVER}} WPACONF=${WLAN_WPACONF[$i]:-${WPACONF}} WPAWAIT=${WLAN_WPAWAIT[$i]:-${WPAWAIT}} [ -n "$VERBOSE" -a -n "$INFO" ] && echo "$0: $1 is '$INFO'" ################### # WIRELESS CONFIG # ################### # Mode needs to be first : some settings apply only in a specific mode! if [ -n "$MODE" ] ; then echo "$0: $IWCOMMAND mode $MODE" | $LOGGER $IWCOMMAND mode $MODE fi # This is a bit hackish, but should do the job right... if [ ! -n "$NICKNAME" ] ; then NICKNAME=`/bin/hostname` fi if [ -n "$ESSID" -o -n "$MODE" ] ; then echo "$0: $IWCOMMAND nick $NICKNAME" | $LOGGER $IWCOMMAND nick $NICKNAME fi # Regular stuff... if [ -n "$NWID" ] ; then echo "$0: $IWCOMMAND nwid $NWID" | $LOGGER $IWCOMMAND nwid $NWID fi if [ -n "$FREQ" ] ; then echo "$0: $IWCOMMAND freq $FREQ" | $LOGGER $IWCOMMAND freq $FREQ elif [ -n "$CHANNEL" ] ; then echo "$0: $IWCOMMAND channel $CHANNEL" | $LOGGER $IWCOMMAND channel $CHANNEL fi # WEP keys (non-WPA) if [ -n "$KEY" -a ! -n "$WPA" ] ; then if [ "$KEY" = "off" ]; then echo "$0: $IWCOMMAND key open" | $LOGGER $IWCOMMAND key open echo "$0: $IWCOMMAND key off" | $LOGGER $IWCOMMAND key off else echo "$0: $IWCOMMAND key restricted" | $LOGGER $IWCOMMAND key restricted echo "$0: $IWCOMMAND key ************" | $LOGGER $IWCOMMAND key $KEY fi fi if [ -n "$SENS" ] ; then echo "$0: $IWCOMMAND sens $SENS" | $LOGGER $IWCOMMAND sens $SENS fi if [ -n "$RATE" ] ; then echo "$0: $IWCOMMAND rate $RATE" | $LOGGER $IWCOMMAND rate $RATE fi if [ -n "$RTS" ] ; then echo "$0: $IWCOMMAND rts $RTS" | $LOGGER $IWCOMMAND rts $RTS fi if [ -n "$FRAG" ] ; then echo "$0: $IWCOMMAND frag $FRAG" | $LOGGER $IWCOMMAND frag $FRAG fi # More specific parameters if [ -n "$IWCONFIG" ] ; then echo "$0: $IWCOMMAND $IWCONFIG" | $LOGGER $IWCOMMAND $IWCONFIG fi if [ -n "$IWSPY" ] ; then echo "$0: $IWSPYCMD $IWSPY" | $LOGGER $IWSPYCMD $IWSPY fi # The iwpriv can set one private IOCTL at the time, so if the $IWPRIV # variable contqins multiple space separated settings, we split them here: # WARNING: if your iwpriv commands contain a WEP/WPA key, these can be logged # in /var/log/messages! if [ -n "$IWPRIV" ] ; then for iwi in $IWPRIV; do echo "$0: $IWPRIVCMD set $iwi" | $LOGGER $IWPRIVCMD set $iwi done fi ################## # WPA_SUPPLICANT # ################## # Support for WPA (wireless protected access) is provided by wpa_supplicant # for those drivers that support it (and it looks like wpa_supplicant is # the future for WPA support in Linux anyway) if [ "$WPA" = "wpa_supplicant" ] || [ "$WPA" = "wpaxsupplicant" ] && [ -x ${SUPPATH}/wpa_supplicant ]; then # Interface down, so wpa_supplicant can associate with the AP $IFCOMMAND down WPACONF=${WPACONF:-/etc/wpa_supplicant.conf} WPA_OPTIONS="" [ ${WPADRIVER} ] && WPA_OPTIONS="-D${WPADRIVER}" # specify the driver [ ${WPA} = "wpaxsupplicant" ] && WPA_OPTIONS="${WPA_OPTIONS} -e" # Use external xsupplicant (disables the internal supplicant) # We leave a running wpa_supplicant process in peace: WPAPID=`echo \`ps axww|grep wpa_supplicant |grep i${INTERFACE}\` |cut -f1 -d' '` if [ ${WPAPID} ]; then echo "$0: wpa_supplicant found running already" | $LOGGER else echo "$0: wpa_supplicant -Bw -c${WPACONF} ${WPA_OPTIONS} -i$INTERFACE" | $LOGGER ${SUPPATH}/wpa_supplicant -Bw -c${WPACONF} ${WPA_OPTIONS} -i$INTERFACE fi # Buy wpa_supplicant some time to authenticate before bringing the # interface back up... but we don't wait forever: # You can increase this value in rc.inet1.conf (WLAN_WPAWAIT) or rc.wireless.conf (WPAWAIT) # if your card takes longer to associate: WPAWAIT=${WPAWAIT:-10} wi=0 while [ $wi -lt $WPAWAIT ]; do wi=$(($wi+1)); sleep 1 if (grep -q "^ctrl_interface=" ${WPACONF}); then if (LC_ALL=C ${SUPPATH}/wpa_cli -i$INTERFACE status|grep -q "^wpa_state=COMPLETED"); then break; fi else if (LC_ALL=C ${IWCOMMAND}|grep -Eq "Encryption key:....-"); then break; fi fi done if [ $wi -eq $WPAWAIT ]; then echo "WPA authentication did not complete, try running '/etc/rc.d/rc.inet1 ${INTERFACE}_start' in a few seconds." | $LOGGER fi # Bring interface up to avoid 'not ready' errors when calling iwconfig $IFCOMMAND up sleep 1 else # ESSID need to be last: most devices re-perform the scanning/discovery # when this is set, and things like encryption keys had better be # defined if we want to discover the right set of APs/nodes. # NOTE: when automatic association does not work, but you manage to get # an IP address by manually setting the ESSID and then calling dhcpcd, # then the cause might be the incorrect definition of your ESSID="bla" # parameter in rc.wireless.conf. # Debug your wireless problems by running 'iwevent' while the card # is being configured. if [ -n "$ESSID" ] ; then echo "$0: $IWCOMMAND essid \"$ESSID\"" | $LOGGER $IWCOMMAND essid "$ESSID" fi fi