openrc/net.BSD/iwconfig.sh
Roy Marples 5af58b4514 Rewrite the core parts in C. We now provide librc so other programs can
query runlevels, services and state without using bash. We also provide
libeinfo so other programs can easily use our informational functions.

As such, we have dropped the requirement of using bash as the init script
shell. We now use /bin/sh and have strived to make the scripts as portable
as possible. Shells that work are bash and dash. busybox works provided
you disable s-s-d. If you have WIPE_TMP set to yes in conf.d/bootmisc you
should disable find too.
zsh and ksh do not work at this time.

Networking support is currently being re-vamped also as it was heavily bash
array based. As such, a new config format is available like so
config_eth0="1.2.3.4/24 5.6.7.8/16"
or like so
config_eth0="'1.2.3.4 netmask 255.255.255.0' '5.6.7.8 netmask 255.255.0.0'"

We will still support the old bash array format provided that /bin/sh IS
a link it bash.

ChangeLog for baselayout-1 can be found in our SVN repo.
2007-04-05 11:18:42 +00:00

563 lines
12 KiB
Bash

# Copyright 2004-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
_config_vars="$_config_vars essid mode associate_timeout preferred_aps blacklist_aps"
iwconfig_depend() {
program /sbin/ifconfig
after plug
before interface
provide wireless
}
iwconfig_get_wep_status() {
local status="disabled"
local mode=$(LC_ALL=C ifconfig "${IFACE}" \
| sed -n -e 's/^[[:space:]]*authmode \([^ ]*\) privacy ON .*/\1/p')
if [ -n "${mode}" ] ; then
status="enabled - ${mode}"
fi
echo "(WEP ${status})"
}
_iwconfig_get() {
LC_ALL=C ifconfig "${IFACE}" | \
sed -n -e 's/^[[:space:]]*ssid \(.*\) channel \([0-9]*\) bssid \(..:..:..:..:..:..\)$/\'"$1"'/p'
}
_get_ssid() {
_iwconfig_get 1
}
_get_ap_mac_address() {
_iwconfig_get 3
}
_get_channel() {
_iwconfig_get 2
}
iwconfig_report() {
local m="connected to"
local ssid=$(_get_ssid)
local mac=$(_get_ap_mac_address "${iface}")
[ -n "${mac}" ] && mac=" at ${mac}"
local wep_status="$(iwconfig_get_wep_status "${iface}")"
local channel=$(_get_channel)
[ -n "${channel}" ] && channel="on channel ${channel} "
eindent
einfo "${IFACE} ${m} \"${ssid}\"${mac}"
einfo "${channel}${wep_status}"
eoutdent
}
iwconfig_get_wep_key() {
local mac="$1" key=
[ -n "${mac}" ] && mac="$(echo "${mac}" | sed -e 's/://g')"
eval key=\$mac_key_${mac}
[ -z "${key}" ] && eval key=\$key_${SSIDVAR}
echo "${key:--}"
}
iwconfig_user_config() {
local conf=
eval set -- \$ifconfig_${SSIDVAR}
for conf in "$@" ; do
ifconfig "${IFACE}" ${conf}
done
}
iwconfig_set_mode() {
local x= opt= unopt="hostap adhoc"
case "${mode}" in
master|hostap) unopt="adhoc" opt="hostap" ;;
ad-hoc|adhoc) unopt="hostap" opt="adhoc" ;;
esac
for x in ${unopt} ; do
ifconfig "${IFACE}" -mediaopt ${x}
done
for x in ${opt} ; do
ifconfig "${IFACE}" mediaopt ${x}
done
}
iwconfig_setup_specific() {
local mode="${1:-master}" channel=
if [ -z "${SSID}" ]; then
eerror "${IFACE} requires an SSID to be set to operate in ${mode} mode"
eerror "adjust the ssid_${IFVAR} setting in /etc/conf.d/net"
return 1
fi
iwconfig_set_mode "${mode}" || return 1
SSIDVAR=$(_shell_var "${SSID}")
local key=$(iwconfig_get_wep_key)
# Now set the key
ifconfig "${IFACE}" wepkey ${key}
ifconfig "${IFACE}" ssid "${ESSID}" || return 1
eval channel=\$channel_${IFVAR}
# We default the channel to 3
ifconfig "${IFACE}" channel "${channel:-3}" || return 1
iwconfig_user_config
iwconfig_report "${iface}"
return 0
}
iwconfig_associate() {
local mac="$1" channel="$2" caps="$3"
local mode= w="(WEP Disabled)" key=
SSIDVAR=$(_shell_var "${SSID}")
key=$(iwconfig_get_wep_key "${mac}")
case "${caps}" in
[EI]P*)
if [ "${key}" = "-" ] ; then
ewarn "WEP key is not set for \"${SSID}\"; not connecting"
return 1
fi
;;
"") ;;
*)
if [ "${key}" != "-" ] ; then
key="-"
ewarn "\"${ESSID}\" is not WEP enabled; ignoring setting"
fi
;;
esac
# Set mode accordingly
case "${caps}" in
*E*) mode="managed"; ifconfig "${IFACE}" -mediaopt adhoc ;;
*I*) mode="adhoc"; ifconfig "${IFACE}" mediaopt adhoc ;;
*)
if LC_ALL=C ifconfig "${IFACE}" | grep -q "^[[:space:]]*media: .*adhoc" ; then
mode="adhoc"
else
mode="managed"
fi
;;
esac
if [ "${key}" = "-" ] ; then
ifconfig "${IFACE}" wepmode off
else
ifconfig "${IFACE}" wepmode on
ifconfig "${IFACE}" deftxkey 1
w=$(iwconfig_get_wep_status)
fi
ebegin "Connecting to \"${SSID}\" in ${mode} mode ${w}"
if ! ifconfig "${IFACE}" wepkey ${key} ; then
eerror "Invalid WEP key ${key}"
return 1
fi
ifconfig "${IFACE}" ssid "${SSID}" || return 1
iwconfig_user_config
if [ "${SSID}" != "any" ] && type preassociate >/dev/null 2>/dev/null ; then
veinfo "Running preassociate function"
veindent
( preassociate )
local e=$?
veoutdent
if [ ${e} -eq 0 ] ; then
veend 1 "preassociate \"${SSID}\" on ${IFACE} failed"
return 1
fi
fi
local timeout= i=0
eval timeout=\$associate_timeout_${IFVAR}
timeout=${timeout:-10}
[ ${timeout} -eq 0 ] \
&& vewarn "WARNING: infinite timeout set for association on ${IFACE}"
while true; do
_has_carrier && break
sleep 1
[ ${timeout} -eq 0 ] && continue
i=$((${i} + 1))
[ ${i} -ge ${timeout} ] && return 1
done
if ! _has_carrier ; then
eend 1
return 1
fi
eend 0
if [ "${SSID}" = "any" ]; then
SSID="$(_get_ssid)"
iwconfig_associate
return $?
fi
iwconfig_report
if type postassociate >/dev/null 2>/dev/null ; then
veinfo "Running postassociate function"
veindent
( postassociate )
veoutdent
fi
return 0
}
iwconfig_scan() {
local x= i=0 scan= quality=
einfo "Scanning for access points"
eindent
scan="$(LC_ALL=C ifconfig -v "${IFACE}" list scan 2>/dev/null | sed -e "1 d" -e "s/$/'/g" -e "s/^/'/g")"
while [ ${i} -lt 3 -o -z "${scan}" ] ; do
scan="${scan}${scan:+ }$(LC_ALL=C ifconfig -v "${IFACE}" scan 2>/dev/null | sed -e "1 d" -e "s/$/'/g" -e "s/^/'/g")"
i=$((${i} + 1))
done
local OIFS=$IFS
APS=-1
eval set -- ${scan}
for line in "$@" ; do
APS=$((${APS} + 1))
set -- ${line}
while true ; do
case "$1" in
*:*:*:*:*:*) break ;;
esac
eval SSID_${APS}="\"\${SSID_${APS}}\${SSID_${APS}:+ }$1\""
shift
done
eval MAC_${APS}="$(echo "$1" | tr '[:lower:]' '[:upper:]')"
eval CHAN_${APS}=$2
quality=${4%:*}
shift ; shift ; shift ; shift ; shift
eval CAPS_${APS}=$*
# Add 1000 for managed nodes as we prefer them to adhoc
set -- $*
case "$1" in
*E*) eval QUAL_${APS}=$((${quality} + 1000)) ;;
*) eval QUAL_${APS}=\$quality ;;
esac
done
if [ -z "${MAC_0}" ]; then
ewarn "no access points found"
eoutdent
return 1
fi
# Sort based on quality
local i=0 k=1 a= b= x= t=
while [ ${i} -lt ${APS} ] ; do
k=$((${i} + 1))
while [ ${k} -le ${APS} ] ; do
eval a=\$QUALITY_${i}
[ -z "${a}" ] && break
eval b=\$QUALITY_${k}
if [ -n "${b}" -a "${a}" -lt "${b}" ] ; then
for x in MAC SSID CHAN QUALITY CAPS ; do
eval t=\$${x}_${i}
eval ${x}_${i}=\$${x}_${k}
eval ${x}_${k}=\$t
done
fi
k=$((${k} + 1))
done
i=$((${i} + 1))
done
# Strip any duplicates
local i=0 k=1 a= b=
while [ ${i} -lt ${APS} ] ; do
k=$((${i} + 1))
while [ ${k} -le ${APS} ] ; do
eval a=\$MAC_${i}
eval b=\$MAC_${k}
if [ "${a}" = "${b}" ] ; then
eval a=\$QUALITY_${i}
eval b=\$QUALITY_${k}
if [ -n "${a}" -a -n "${b}" ] ; then
if [ ${a} -ge ${b} ] ; then
unset MAC_${k} SSID_${k} CHAN_${k} QUALITY_${k} CAPS_${k}
else
unset MAC_${i} SSID_${i} CHAN_${i} QUALITY_${i} CAPS_${i}
fi
else
unset MAC_${k} SSID_${k} CHAN_${k} QUALITY_${k} CAPS_${k}
fi
fi
k=$((${k} + 1))
done
i=$((${i} + 1))
done
local i=0 e= m= black= s=
eval "$(_get_array "blacklist_aps")"
black="$@"
while [ ${i} -le ${APS} ] ; do
eval x=\$MAC_${i}
if [ -z "${x}" ] ; then
i=$((${i} + 1))
continue
fi
eval m=\$MODE_${i}
[ -n "${m}" ] && m=", ${m}"
eval s=\$SSID_${i}
eval q=\$QUALITY_${i}
eval e=\$CAPS_${i}
case "${e}" in
[EI]P*) e=", encrypted" ;;
*) e="" ;;
esac
if [ -z "${s}" ] ; then
einfo "Found ${x}${m}${e}"
else
einfo "Found \"${s}\" at ${x}${m}${e}"
fi
x="$(echo "${x}" | sed -e 's/://g')"
eval x=\$mac_ssid_${x}
if [ -n "${x}" ] ; then
eval SSID_${i}=\$x
s=${x}
eindent
einfo "mapping to \"${x}\""
eoutdent
fi
eval "$(_get_array "blacklist_aps")"
for x in "$@" ; do
if [ "${x}" = "${s}" ] ; then
ewarn "${s} has been blacklisted - not connecting"
unset SSID_${i} MAC_${i} CHAN_${i} QUALITY_${i} CAPS_${i}
fi
done
i=$((${i} + 1))
done
eoutdent
return 0
}
iwconfig_force_preferred() {
[ -z "${preferred_aps}" ] && return 1
ewarn "Trying to force preferred in case they are hidden"
eval "(_get_array "preferred_aps")"
local ssid=
for ssid in "$@"; do
local found_AP=false i=0 e=
while [ ${i} -le ${APS} ] ; do
eval e=\$SSID_${i}
if [ "${e}" = "${ssid}" ] ; then
found_AP=true
break
fi
i=$((${i} + 1))
done
if ! ${found_AP} ; then
SSID=${e}
iwconfig_associate && return 0
fi
done
ewarn "Failed to associate with any preferred access points on ${IFACE}"
return 1
}
iwconfig_connect_preferred() {
local essid= i=0 mode= mac= caps= freq= chan=
eval "$(_get_array preferred_aps)"
for essid in "$@"; do
while [ ${i} -le ${APS} ] ; do
eval e=\$SSID_${i}
if [ "${e}" = "${essid}" ] ; then
SSID=${e}
eval mac=\$MAC_${i}
eval caps=\$CAPS_${i}
eval freq=\$FREQ_${i}
eval chan=\$CHAN_${i}
iwconfig_associate "${mac}" \
"${chan}" "${caps}" && return 0
fi
i=$((${i} + 1))
done
done
return 1
}
iwconfig_connect_not_preferred() {
local essid= i=0 mode= mac= caps= freq= chan= pref=
while [ ${i} -le ${APS} ] ; do
eval e=\$SSID_${i}
if [ -z "${e}" ] ; then
i=$((${i} + 1))
continue
fi
eval "$(_get_array preferred_aps)"
pref=false
for essid in "$@" ; do
if [ "${e}" = "${essid}" ] ; then
pref=true
break
fi
done
if ! ${pref} ; then
SSID=${e}
eval mac=\$MAC_${i}
eval caps=\$CAPS_${i}
eval freq=\$FREQ_${i}
eval chan=\$CHAN_${i}
iwconfig_associate "${mac}" \
"${chan}" "${caps}" && return 0
fi
i=$((${i} + 1))
done
return 1
}
iwconfig_defaults() {
# Set some defaults
#ifconfig "${iface}" txpower 100 2>/dev/null
ifconfig "${IFACE}" bssid -
ifconfig "${IFACE}" ssid -
ifconfig "${IFACE}" authmode open
ifconfig "${IFACE}" -mediaopt adhoc
ifconfig "${IFACE}" -mediaopt hostap
}
iwconfig_configure() {
local x APS
eval SSID=\$ssid_${IFVAR}
# Setup ad-hoc mode?
eval x=\$mode_${IFVAR}
x=${x:-managed}
case "${x}" in
ad-hoc|adhoc|hostap|master) iwconfig_setup_specific "${x}" ;;
esac
if [ "${x}" != "managed" -a "${x}" != "auto" ] ; then
eerror "Only managed, ad-hoc, master and auto modes are supported"
return 1
fi
# Has an ESSID been forced?
if [ -n "${SSID}" ]; then
iwconfig_set_mode "${x}"
iwconfig_associate && return 0
[ "${SSID}" = "any" ] && iwconfig_force_preferred && return 0
eval SSID=\$adhoc_ssid_${IFVAR}
if [ -n "${SSID}" ]; then
iwconfig_setup_specific adhoc
return $?
fi
return 1
fi
# Do we have a preferred Access Point list specific to the interface?
# x="preferred_aps_${ifvar}[@]"
# [[ -n ${!x} ]] && preferred_aps=( "${!x}" )
# # Do we have a blacklist Access Point list specific to the interface?
# x="blacklist_aps_${ifvar}[@]"
# [[ -n ${!x} ]] && blacklist_aps=( "${!x}" )
# Are we forcing preferred only?
eval x=\$associate_order_${IFVAR}
[ -n "${x}" ] && associate_order=${x}
associate_order=${associate_order:-any}
if [ "${associate_order}" = "forcepreferredonly" ]; then
iwconfig_force_preferred && return 0
else
iwconfig_scan || return 1
iwconfig_connect_preferred && return 0
[ "${associate_order}" = "forcepreferred" ] || \
[ "${associate_order}" = "forceany" ] && \
iwconfig_force_preferred && return 0
[ "${associate_order}" = "any" ] || \
[ "${associate_order}" = "forceany" ] && \
iwconfig_connect_not_preferred && return 0
fi
e="associate with"
[ -z "${MAC_0}" ] && e="find"
[ "${preferred_aps}" = "force" ] || \
[ "${preferred_aps}" = "forceonly" ] && \
e="force"
e="Couldn't ${e} any access points on ${IFACE}"
eval SSID=\$adhoc_ssid_${IFVAR}
if [ -n "${SSID}" ]; then
ewarn "${e}"
iwconfig_setup_specific adhoc
return $?
fi
eerror "${e}"
return 1
}
iwconfig_pre_start() {
# We don't configure wireless if we're being called from
# the background
${IN_BACKGROUND} && return 0
save_options "SSID" ""
_exists || return 0
if ! _is_wireless ; then
veinfo "${IFACE} is not wireless"
return 0
fi
iwconfig_defaults
iwconfig_user_config
# Set the base metric to be 2000
metric=2000
einfo "Configuring wireless network for ${IFACE}"
if iwconfig_configure ; then
save_options "ESSID" "${ESSID}"
return 0
fi
eerror "Failed to configure wireless for ${IFACE}"
iwconfig_defaults
#iwconfig "${IFACE}" txpower 0 2>/dev/null
unset SSID SSIDVAR
_down
return 1
}
iwconfig_post_stop() {
${IN_BACKGROUND} && return 0
_is_wireless || return 0
iwconfig_defaults
#iwconfig "${IFACE}" txpower 0 2>/dev/null
}
# vim: set ts=4