From 5af58b45146ab5253ca964738f4e45287bf963d4 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Thu, 5 Apr 2007 11:18:42 +0000 Subject: 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. --- net.BSD/Makefile | 5 + net.BSD/ifconfig.sh | 125 ++++++++++++ net.BSD/iwconfig.sh | 562 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 692 insertions(+) create mode 100644 net.BSD/Makefile create mode 100644 net.BSD/ifconfig.sh create mode 100644 net.BSD/iwconfig.sh (limited to 'net.BSD') diff --git a/net.BSD/Makefile b/net.BSD/Makefile new file mode 100644 index 00000000..11bd20a4 --- /dev/null +++ b/net.BSD/Makefile @@ -0,0 +1,5 @@ +DIR = /$(LIB)/rcscripts/net +FILES = ifconfig.sh iwconfig.sh + +TOPDIR = .. +include $(TOPDIR)/default.mk diff --git a/net.BSD/ifconfig.sh b/net.BSD/ifconfig.sh new file mode 100644 index 00000000..2e88bc20 --- /dev/null +++ b/net.BSD/ifconfig.sh @@ -0,0 +1,125 @@ +# Copyright 2004-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +ifconfig_depend() { + program /sbin/ifconfig + provide interface +} + +_exists() { + [ -e /dev/net/"${IFACE}" ] +} + +_get_mac_address() { + local mac=$(LC_ALL=C ifconfig "${IFACE}" | \ + sed -n -e 's/^[[:space:]]*ether \(..:..:..:..:..:..\).*/\1/p') + + case "${mac}" in + 00:00:00:00:00:00) ;; + 44:44:44:44:44:44) ;; + FF:FF:FF:FF:FF:FF) ;; + *) echo "${mac}"; return 0 ;; + esac + + return 1 +} + +_up () { + ifconfig "${IFACE}" up +} + +_down () { + ifconfig "${IFACE}" down +} + +_ifindex() { + local x= + for x in /dev/net[0-9]* ; do + if [ "${x}" -ef /dev/net/"${IFACE}" ] ; then + echo "${x#/dev/net}" + return 0 + fi + done + return 1 +} + +_is_wireless() { + LC_ALL=C ifconfig "${IFACE}" 2>/dev/null | \ + grep -q "^[[:space:]]*media: IEEE 802.11 Wireless" +} + +_get_inet_address() { + set -- $(LC_ALL=C ifconfig "${IFACE}" | + sed -n -e 's/^[[:space:]]*inet \([^ ]*\) netmask 0x\(..\)\(..\)\(..\)\(..\).*/\1 0x\2.0x\3.0x\4/p') + echo -n "$1" + shift + + echo "/$(_netmask2cidr "$1")" +} + +_add_address() { + if [ "${metric:-0}" != "0" ] ; then + set -- "$@" metric ${metric} + fi + + ifconfig "${IFACE}" add "$@" +} + +_add_route() { + if [ $# -gt 3 ] ; then + if [ "$3" = "gw" -o "$3" = "via" ] ; then + local one=$1 two=$2 + shift ; shift; shift + set -- "${one}" "${two}" "$@" + fi + fi + + route add "$@" +} + +_delete_addresses() { + # We don't remove addresses from aliases + case "${IFACE}" in + *:*) return 0 ;; + esac + + einfo "Removing addresses" + eindent + local addr= + for addr in $(LC_ALL=C ifconfig "${IFACE}" | + sed -n -e 's/^[[:space:]]*inet \([^ ]*\).*/\1/p') ; do + if [ "${addr}" = "127.0.0.1" ] ; then + # Don't delete the loopback address + [ "$1" = "lo" -o "$1" = "lo0" ] && continue + fi + einfo "${addr}" + /sbin/ifconfig "$1" delete "${addr}" + eend $? + done + + # Remove IPv6 addresses + for addr in $(LC_ALL=C ifconfig "${IFACE}" | \ + sed -n -e 's/^[[:space:]]*inet6 \([^ ]*\).*/\1/p') ; do + case "${addr}" in + *"%${IFACE}") continue ;; + ::1) continue ;; + esac + einfo "${addr}" + /sbin/ifconfig "${IFACE}" inet6 delete "${addr}" + eend $? + done + + return 0 +} + +_show_address() { + einfo "received address $(_get_inet_address "${IFACE}")" +} + +_has_carrier() { + local s=$(LC_ALL=C ifconfig "${IFACE}" | \ + sed -n -e 's/^[[:space:]]status: \(.*\)$/\1/p') + [ -z "${s}" -o "${s}" = "active" -o "${s}" = "associated" ] +} + +# vim: set ts=4 : diff --git a/net.BSD/iwconfig.sh b/net.BSD/iwconfig.sh new file mode 100644 index 00000000..912e0792 --- /dev/null +++ b/net.BSD/iwconfig.sh @@ -0,0 +1,562 @@ +# 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 -- cgit v1.2.3