summaryrefslogtreecommitdiffstats
path: root/src/connections
diff options
context:
space:
mode:
authorJames Rayner <james@archlinux.org>2009-08-07 16:23:45 +0200
committerJames Rayner <james@archlinux.org>2009-08-07 16:23:45 +0200
commit54e39849f1e60eb043f9d8f0904acf3c79d96a1c (patch)
tree9c10a01ea0ba58d31b3ab8282ead767da49264d3 /src/connections
parentf7168ae05837a24060b41511be6e4626cb26828a (diff)
downloadnetctl-54e39849f1e60eb043f9d8f0904acf3c79d96a1c.tar.gz
netctl-54e39849f1e60eb043f9d8f0904acf3c79d96a1c.tar.xz
Patch from Jim Pryor
Diffstat (limited to 'src/connections')
-rw-r--r--src/connections/ethernet211
-rw-r--r--src/connections/ethernet-iproute214
-rw-r--r--src/connections/ppp53
-rw-r--r--src/connections/wireless368
4 files changed, 693 insertions, 153 deletions
diff --git a/src/connections/ethernet b/src/connections/ethernet
index e24e9f5..933dbd6 100644
--- a/src/connections/ethernet
+++ b/src/connections/ethernet
@@ -1,86 +1,114 @@
#! /bin/bash
+
+##################################
+##
+# /usr/lib/network/connections/ethernet
+##
+##################################
+
+. /etc/rc.conf
+. /etc/rc.d/functions
. /usr/lib/network/network
ethernet_up() {
- load_profile $1
+ load_profile "$1"
- if [[ ! -e /sys/class/net/"$INTERFACE" ]]; then
- if ! echo "$INTERFACE"|grep ":"; then
- err_append "interface $INTERFACE does not exist"
+ if [[ ! -e "/sys/class/net/$INTERFACE" ]]; then
+ if ! echo "$INTERFACE" | fgrep -q ":"; then
+ report_fail "Interface $INTERFACE does not exist."
return 1
fi
fi
- ip link set $INTERFACE up
- sleep 1
+ report_debug ethernet_up ifup
+ ethernet_control "$INTERFACE" up
+ sleep 3
- if ip link show $INTERFACE|grep -q "NO-CARRIER"; then
- err_append "No connection"
+ # don't think it's possible to detect carrier using ifconfig alone (at least, not without ifdown/ifupping the interface)
+ # if ip link show dev "$INTERFACE" | fgrep -q "NO-CARRIER"; then...
+ # if ! ethernet_query "$INTERFACE" address; then...
+ if [[ $(cat /sys/class/net/$INTERFACE/carrier 2>/dev/null) -ne 1 ]]; then # gives err if iface inactive (i.e. ifdown)
+ # 0 if up but not connected to network, 1 if connected
+ report_fail "No connection."
return 1
fi
if checkyesno "${AUTH8021X:-no}"; then
- . "${SUBR_DIR}"/8021x
+ . "$SUBR_DIR/8021x"
[[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf"
[[ -z "$WPA_OPTS" ]] && WPA_OPTS="-Dwired"
+ report_debug ethernet_up start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
if ! wpa_check "$INTERFACE"; then
- ifconfig "$INTERFACE" down
+ ethernet_control "$INTERFACE" forcedown # JP: forcedown ignores the nodown quirk, matching
+ # what was already here in the code...do we in fact want to ignore
+ # the nodown quirk here?
return 1
fi
fi
- case $IP in
+ case "$IP" in
dhcp)
if checkyesno "${DHCLIENT:-no}"; then
- rm -r /var/run/dhclient-${INTERFACE}.pid >/dev/null 2>&1
- if ! dhclient -q -e TIMEOUT="${DHCP_TIMEOUT:-10}" -pf /var/run/dhclient-${INTERFACE}.pid $INTERFACE; then
- err_append "DHCP IP lease attempt failed."
+ rm -r "/var/run/dhclient-$INTERFACE.pid" >/dev/null 2>&1
+ report_debug ethernet_up dhclient -q -e TIMEOUT="${DHCP_TIMEOUT:-10}" -pf "/var/run/dhclient-$INTERFACE.pid" "$INTERFACE"
+ if ! dhclient -q -e TIMEOUT="${DHCP_TIMEOUT:-10}" -pf "/var/run/dhclient-$INTERFACE.pid" "$INTERFACE"; then
+ report_fail "Couldn't get DHCP IP lease."
return 1
fi
else
# Clear remaining pid files.
- rm -f /var/run/dhcpcd-${INTERFACE}.{pid,cache} >/dev/null 2>&1
+ rm -f "/var/run/dhcpcd-$INTERFACE".{pid,cache} >/dev/null 2>&1
# If using own dns, tell dhcpcd to NOT replace resolv.conf
- [[ -n "$DNS1" ]] && DHCP_OPTIONS="-C resolv.conf $DHCP_OPTIONS"
- # Start dhcpcd
- if ! dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE"; then
- err_append "DHCP IP lease attempt failed."
+ [[ -n "$DNS1" || -n "$DNS" ]] && DHCP_OPTIONS="-C resolv.conf $DHCP_OPTIONS"
+
+ #if ! dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE" >/dev/null 2>&1; then
+ report_debug ethernet_up dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE"
+ dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE" 2>&1 | report_debug $(cat)
+ if [[ "$PIPESTATUS" -ne 0 ]]; then
+ report_fail "Couldn't get DHCP IP lease."
return 1
fi
fi
- [[ -n "$IFOPTS" ]] && ifconfig "$INTERFACE" $IFOPTS
+ if [[ -n "$IFOPTS" ]]; then
+ report_debug ethernet_up ifup $IFOPTS
+ ifconfig "$INTERFACE" $IFOPTS
+ fi
;;
static)
+ report_debug ethernet_up ifup $IFOPTS
if ! ifconfig "$INTERFACE" $IFOPTS up; then
- err_append "Bringing interface up failed."
+ report_fail "Couldn't configure $INTERFACE interface."
return 1
fi
# bring up the default route (gateway)
if [[ -n "$GATEWAY" ]]; then
- if ! route add default gw $GATEWAY; then
- err_append "Adding gateway failed."
+ report_debug ethernet_up route add default gw "$GATEWAY"
+ if ! route add default gw "$GATEWAY"; then
+ ethernet_control "$INTERFACE" down # JP: don't we want to take the interface down if we failed (as ethernet-iproute does?)
+ report_fail "Couldn't add gateway $GATEWAY."
return 1
fi
fi
;;
*)
- err_append "IP=\"\" must be either 'dhcp' or 'static'."
+ report_err "Profile error: must be either IP=dhcp or IP=static."
return 1
;;
esac
# set the hostname
if [[ -n "$HOSTNAME" ]]; then
+ report_debug ethernet_up hostname "$HOSTNAME"
if ! hostname "$HOSTNAME"; then
- err_append "Setting hostname failed."
+ report_fail "Couldn't set hostname."
return 1
fi
fi
# Generate a new resolv.conf
- if [[ -n "$DNS1" ]] || [[ -n "$DNS" ]]; then
+ if [[ -n "$DNS1" || -n "$DNS" ]]; then
: >/etc/resolv.conf
[[ -n "$DOMAIN" ]] && echo "domain $DOMAIN" >>/etc/resolv.conf
@@ -94,36 +122,141 @@ ethernet_up() {
done
fi
fi
+
+ # successfully running a new profile; erase any suspended profiles on this interface
+ local iface="$INTERFACE"
+ find "$STATE_DIR/suspend/" -maxdepth 1 -type f -printf '%f\n' \
+ | while read prof; do
+ # the pipe to "while read" will create a subshell, so sourced variables will already be in a sandbox
+ # we just need to clear INTERFACE which is all we care about
+ unset INTERFACE
+ . "$STATE_DIR/suspend/$prof"
+ if [[ "$iface" == "$INTERFACE" ]]; then
+ rm "$STATE_DIR/suspend/$prof"
+ fi
+ done
+
return 0
}
ethernet_down() {
- load_profile $1
- case $IP in
+ load_profile "$1"
+ case "$IP" in
dhcp)
if checkyesno "${DHCLIENT:-no}"; then
- if [[ -f /var/run/dhclient-${INTERFACE}.pid ]]; then
- kill `cat /var/run/dhclient-${INTERFACE}.pid`
+ if [[ -f "/var/run/dhclient-$INTERFACE.pid" ]]; then
+ report_debug ethernet_down kill dhclient
+ kill $(cat "/var/run/dhclient-$INTERFACE.pid")
fi
else
- if [[ -f /var/run/dhcpcd-${INTERFACE}.pid ]]; then
- dhcpcd -qx "$INTERFACE"
+ if [[ -f "/var/run/dhcpcd-$INTERFACE.pid" ]]; then
+ report_debug ethernet_down dhcpcd -qx "$INTERFACE"
+ dhcpcd -qx "$INTERFACE" >/dev/null 2>&1
fi
fi
;;
static)
- [[ -n "$GATEWAY" ]] && route del default gw $GATEWAY
+ if [[ -n "$GATEWAY" ]]; then
+ report_debug ethernet_down route del default gw "$GATEWAY"
+ route del default gw "$GATEWAY"
+ fi
;;
esac
- ifconfig $INTERFACE 0.0.0.0
-
- case "$CONNECTION" in # Keep interface up for wireless
- ethernet|ethernet-old)
- quirk "nodown" || ifconfig $INTERFACE down
+
+ report_debug ethernet_down ifdown
+ ethernet_control "$INTERFACE" down
+}
+
+# CONNECTION_query $INTERFACE [ profile | enabled (i.e. not rfkill-ed) | active (i.e. ifup'd) | associated | address ]
+ethernet_query() {
+ local INTERFACE="$1" REQUEST="$2"
+ # report_debug ethernet_query "$@"
+ case "$REQUEST" in
+
+ # JP: this duplicates code in ethernet-iproute, but doing so was necessary to refactor these functions into the CONNECTION scripts
+ profile)
+ # return code = 1 if iface is available to be used
+ # return code = 0 if unavailable (disabled, or in use by another profile or by external config)
+ # echo "" | "disabled" | "external" | PROFILE_NAME
+ if [[ ! -f "$STATE_DIR/interfaces/$INTERFACE" ]]; then
+ # interface is up but has no registered profile
+ if ethernet_query "$INTERFACE" address; then
+ set_iface up "$INTERFACE" external
+ echo "external"
+ return 0
+ fi
+ # no ip address, count as inactive
+ # should we ifconfig iface down? no, may be up for a reason
+ return 1
+
+ else # interface is up and thinks it's running a profile
+ . "$STATE_DIR/interfaces/$INTERFACE" # these files should only contain a PROFILE=... statement
+ case "$PROFILE" in
+ external)
+ echo "external"
+ return 0
+ ;;
+ disabled) # shouldn't happen for non-wireless interfaces, but leaving this here in case...
+ # iface should be down if it's disabled
+ ethernet_control "$INTERFACE" down
+ echo "disabled"
+ return 0
+ ;;
+ *)
+ ( # use subshell to prevent overwriting currently loaded profile
+ . "$STATE_DIR/profiles/$PROFILE"
+ if ! ethernet_query "$INTERFACE" address; then
+ report_warn "INTERFACE $INTERFACE is inactive; no longer being controlled by $PROFILE"
+ set_profile down "$PROFILE"
+ exit 1
+ else
+ echo "$PROFILE" # associated with loaded profile
+ exit 0
+ fi
+ )
+ # return $?
+ ;;
+ esac
+ fi
+ ;;
+
+ active)
+ ifconfig "$INTERFACE" | fgrep -qw UP
+ # cat /sys/class/net/wlan0/carrier >/dev/null # gives err if iface inactive, 0 if up but not connected to network, 1 if connected
+ ;;
+
+ address)
+ ifconfig "$INTERFACE" | fgrep -q addr:
+ ;;
+
+ *) return 1 ;;
+ esac
+}
+
+# CONNECTION_control $INTERFACE [ up | down | forcedown | enable | disable ]
+ethernet_control() {
+ local INTERFACE="$1" ACTION="$2"
+ #report_debug ethernet_control "$@"
+ case "$ACTION" in
+ up) ifconfig "$INTERFACE" up 2>/dev/null
+ ethernet_query "$INTERFACE" active
+ ;;
+ down|forcedown)
+ ifconfig "$1" 0.0.0.0
+ if [[ "$2" = forcedown ]] || ! quirk nodown; then
+ ifconfig "$INTERFACE" down
+ fi
+ ;;
+ *) return 1
;;
esac
}
-ethernet_$1 $2
+ethernet_verify() {
+ local INTERFACE="$1"
+ # do nothing
+}
+
+ethernet_$1 "$2" "$3"
exit $?
# vim: set ts=4 et sw=4:
diff --git a/src/connections/ethernet-iproute b/src/connections/ethernet-iproute
index 1a4a6e4..8ecabe8 100644
--- a/src/connections/ethernet-iproute
+++ b/src/connections/ethernet-iproute
@@ -1,85 +1,102 @@
#! /bin/bash
+
+##################################
+##
+# /usr/lib/network/connections/ethernet-iproute
+##
+##################################
+
+. /etc/rc.conf
+. /etc/rc.d/functions
. /usr/lib/network/network
-error()
-{
- err_append "$*"
- ip addr flush $INTERFACE &>/dev/null
- quirk "nodown" || ip link set $INTERFACE down &>/dev/null
+report_iproute() {
+ report_"$@"
+ ethernet_control "$INTERFACE" down
exit 1
}
ethernet_up() {
- load_profile $1
+ load_profile "$1"
- if [[ ! -e /sys/class/net/$INTERFACE ]]; then
- if ! echo "$INTERFACE"|grep ":"; then
- error "Interface $INTERFACE does not exist"
+ if [[ ! -e "/sys/class/net/$INTERFACE" ]]; then
+ if ! echo "$INTERFACE" | fgrep -q ":"; then
+ report_iproute fail "Interface $INTERFACE does not exist."
fi
fi
- ip link set $INTERFACE up
- sleep 1
+ report_debug ethernet_iproute_up ifup
+ ethernet_control "$INTERFACE" up
+ sleep 3
- if ip link show $INTERFACE|grep -q "NO-CARRIER"; then
- err_append "No connection"
- return 1
+ # if ! ethernet_query "$INTERFACE" address; then...
+ if ip link show dev "$INTERFACE" | fgrep -q "NO-CARRIER"; then # JP: shouldn''t we include the "dev"?
+ report_iproute fail "No connection."
fi
-
- if checkyesno ${AUTH8021X:-no}; then
- . ${SUBR_DIR}/8021x
+
+ if checkyesno "${AUTH8021X:-no}"; then
+ . "$SUBR_DIR/8021x"
[[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf"
[[ -z "$WPA_OPTS" ]] && WPA_OPTS="-Dwired"
-
+ report_debug ethernet_iproute_up start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
if ! wpa_check "$INTERFACE"; then
- ip link set $INTERFACE down
+ ethernet_control "$INTERFACE" forcedown # JP: forcedown ignores the nodown quirk, matching
+ # what was already here in the code...do we in fact want to ignore
+ # the nodown quirk here?
return 1
fi
fi
- case $IP in
+ case "$IP" in
dhcp)
# Clear remaining pid files.
- rm -f /var/run/dhcpcd-${INTERFACE}.{pid,cache} >/dev/null 2>&1
-
+ rm -f "/var/run/dhcpcd-$INTERFACE".{pid,cache} >/dev/null 2>&1
# If using own dns, tell dhcpcd to NOT replace resolv.conf
[[ -n "$DNS" ]] && DHCP_OPTIONS="-C resolv.conf $DHCP_OPTIONS"
-
- if ! dhcpcd -qL -t ${DHCP_TIMEOUT:-10} $DHCP_OPTIONS $INTERFACE; then
- error "DHCP IP lease attempt failed"
+
+ #if ! dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE" >/dev/null 2>&1; then
+ report_debug ethernet_iproute_up dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE"
+ dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" $DHCP_OPTIONS "$INTERFACE" 2>&1 | report_iproute debug $(cat)
+ if [[ "$PIPESTATUS" -ne 0 ]]; then
+ report_iproute fail "Couldn't get DHCP IP lease."
fi
;;
static)
if [[ -n "$ADDR" ]]; then
- if ! ip addr add ${ADDR}/24 brd + dev $INTERFACE; then
- error "Could not configure interface"
+ report_debug ethernet_iproute_up ip addr add "$ADDR/24" brd + dev "$INTERFACE"
+ if ! ip addr add "$ADDR/24" brd + dev "$INTERFACE"; then
+ report_iproute fail "Couldn't configure $INTERFACE interface."
fi
fi
if [[ -n "$GATEWAY" ]]; then
- if ! ip route add default via $GATEWAY; then
- error "Adding gateway failed"
+ report_debug ethernet_iproute_up ip route add default via "$GATEWAY"
+ if ! ip route add default via "$GATEWAY"; then
+
+ report_iproute fail "Couldn't add gateway $GATEWAY."
fi
fi
;;
*)
- error "Profile error: IP must be either 'dhcp' or 'static'"
+ report_iproute err "Profile error: must be either IP=dhcp or IP=static."
;;
esac
if [[ -n "$IPCFG" ]]; then
for line in "${IPCFG[@]}"; do
- if ! ip $line; then
- error "Could not configure interface"
+ report_debug ethernet_iproute_up ip "$line"
+ if ! ip "$line"; then
+ report_iproute fail "Couldn't configure $INTERFACE interface ($line)."
fi
done
fi
- # Set hostname
+ # set the hostname
if [[ -n "$HOSTNAME" ]]; then
- if ! hostname $HOSTNAME; then
- error "Cannot set hostname"
+ report_debug ethernet_iproute_up hostname "$HOSTNAME"
+ if ! hostname "$HOSTNAME"; then
+ report_iproute fail "Couldn't set hostname."
fi
fi
@@ -89,29 +106,132 @@ ethernet_up() {
[[ -n "$DOMAIN" ]] && echo "domain $DOMAIN" >>/etc/resolv.conf
[[ -n "$SEARCH" ]] && echo "search $SEARCH" >>/etc/resolv.conf
- if [[ -n "$DNS" ]]; then
- for dns in ${DNS[@]}; do
- echo "nameserver $dns" >>/etc/resolv.conf
- done
- fi
+ for dns in "${DNS[@]}"; do
+ echo "nameserver $dns" >>/etc/resolv.conf
+ done
fi
+
+ # successfully running a new profile; erase any suspended profiles on this interface
+ local iface="$INTERFACE"
+ find "$STATE_DIR/suspend/" -maxdepth 1 -type f -printf '%f\n' \
+ | while read prof; do
+ # the pipe to "while read" will create a subshell, so sourced variables will already be in a sandbox
+ # we just need to clear INTERFACE which is all we care about
+ unset INTERFACE
+ . "$STATE_DIR/suspend/$prof"
+ if [[ "$iface" == "$INTERFACE" ]]; then
+ rm "$STATE_DIR/suspend/$prof"
+ fi
+ done
+
return 0
}
ethernet_down() {
- load_profile $1
+ load_profile "$1"
- if [[ "$IP" == "dhcp" ]]; then
- if [[ -f /var/run/dhcpcd-${INTERFACE}.pid ]]; then
- dhcpcd -qx $INTERFACE
+ if [[ "$IP" == dhcp ]]; then
+ if [[ -f "/var/run/dhcpcd-$INTERFACE.pid" ]]; then
+ report_debug ethernet_iproute_down dhcpcd -qx "$INTERFACE"
+ dhcpcd -qx "$INTERFACE" >/dev/null 2>&1
fi
fi
- ip addr flush $INTERFACE
- quirk "nodown" || ip link set $INTERFACE down
+ report_debug ethernet_iproute_down if_down
+ ethernet_control "$INTERFACE" down
+}
+
+# CONNECTION_query $INTERFACE [ profile | enabled (i.e. not rfkill-ed) | active (i.e. ifup'd) | associated | address ]
+ethernet_query() {
+ local INTERFACE="$1" REQUEST="$2"
+ # report_debug ethernet_iproute_query "$@"
+ case "$REQUEST" in
+
+ profile)
+ # return code = 1 if iface is available to be used
+ # return code = 0 if unavailable (disabled, or in use by another profile or by external config)
+ # echo "" | "disabled" | "external" | PROFILE_NAME
+ if [[ ! -f "$STATE_DIR/interfaces/$INTERFACE" ]]; then
+ # interface is up but has no registered profile
+ if ethernet_query "$INTERFACE" address; then
+ set_iface up "$INTERFACE" external
+ echo "external"
+ return 0
+ fi
+ # no ip address, count as inactive
+ # should we ifconfig iface down? no, may be up for a reason
+ return 1
+
+ else # interface is up and thinks it's running a profile
+ . "$STATE_DIR/interfaces/$INTERFACE" # these files should only contain a PROFILE=... statement
+ case "$PROFILE" in
+ external)
+ echo "external"
+ return 0
+ ;;
+ disabled) # shouldn't happen for non-wireless interfaces, but leaving this here in case...
+ # iface should be down if it's disabled
+ ethernet_control "$INTERFACE" down
+ echo "disabled"
+ return 0
+ ;;
+ *)
+ ( # use subshell to prevent overwriting currently loaded profile
+ . "$STATE_DIR/profiles/$PROFILE"
+ if ! ethernet_query "$INTERFACE" address; then
+ report_warn "INTERFACE $INTERFACE is inactive; no longer being controlled by $PROFILE"
+ set_profile down "$PROFILE"
+ exit 1
+ else
+ echo "$PROFILE" # associated with loaded profile
+ exit 0
+ fi
+ )
+ # return $?
+ ;;
+ esac
+ fi
+ ;;
+
+ active)
+ ip -o link show dev "$INTERFACE" | egrep -qw '^[^>]*,UP' # man ip is inconsistent about whether to use "dev"
+ # cat /sys/class/net/wlan0/carrier >/dev/null # gives err if iface inactive, 0 if up but not connected to network, 1 if connected
+ ;;
+
+ address)
+ test -n "$(ip -o addr show dev "$INTERFACE" | sed -n '2p')"
+ # ip link show dev "$INTERFACE" | fgrep -q "NO-CARRIER"
+ ;;
+
+ *) return 1 ;;
+ esac
+}
+
+# CONNECTION_control $INTERFACE [ up | down | forcedown | enable | disable ]
+ethernet_control() {
+ local INTERFACE="$1" ACTION="$2"
+ #report_debug ethernet_iproute_control "$@"
+ case "$ACTION" in
+ up)
+ ip link set dev "$INTERFACE" up 2>/dev/null # man ip is inconsistent about whether to use "dev"
+ ethernet_query "$INTERFACE" active
+ ;;
+ down|forcedown)
+ ip addr flush dev "$INTERFACE" &>/dev/null
+ if [[ "$2" = forcedown ]] || ! quirk nodown; then
+ ip link set dev "$INTERFACE" down &>/dev/null # man ip is inconsistent about whether to use "dev"
+ fi
+ ;;
+ *) return 1
+ ;;
+ esac
+}
+ethernet_verify() {
+ local INTERFACE="$1"
+ # do nothing
}
-ethernet_$1 $2
+ethernet_$1 "$2" "$3"
exit $?
# vim: set ts=4 et sw=4:
diff --git a/src/connections/ppp b/src/connections/ppp
index 9432323..ce3c8ab 100644
--- a/src/connections/ppp
+++ b/src/connections/ppp
@@ -1,25 +1,58 @@
#! /bin/bash
+##################################
+##
+# /usr/lib/network/connections/ppp
+##
+##################################
+
+. /etc/rc.conf
+. /etc/rc.d/functions
. /usr/lib/network/network
ppp_up() {
- load_profile $1
- [[ -z "$PEER" ]] && PEER="provider"
+ load_profile "$1"
+ [[ -z "$PEER" ]] && PEER=provider
[[ -z "$PPP_TIMEOUT" ]] && PPP_TIMEOUT=30
- /usr/sbin/pppd call $PEER updetach child-timeout $PPP_TIMEOUT linkname $PEER
-
- if [[ $? -ne 0 ]]; then
- err_append "pppd connection failed"
- exit 1
+ if ! /usr/sbin/pppd call "$PEER" updetach child-timeout "$PPP_TIMEOUT" linkname "$PEER"; then
+ report_fail "Couldn't make pppd connection."
+ return 1
fi
+
+ # wireless and wireless-dbus connections run this block when they call "ethernet up"; but ppp needs to do it itself
+ # successfully running a new profile; erase any suspended profiles on this interface
+ local interface="$INTERFACE"
+ find "$STATE_DIR/suspend/" -maxdepth 1 -type f -printf '%f\n' \
+ | while read prof; do
+ # the pipe to "while read" will create a subshell, so sourced variables will already be in a sandbox
+ # we just need to clear INTERFACE which is all we care about
+ unset INTERFACE
+ . "$STATE_DIR/suspend/$prof"
+ if [[ "$interface" == "$INTERFACE" ]]; then
+ rm "$STATE_DIR/suspend/$prof"
+ fi
+ done
}
ppp_down() {
- load_profile $1
- kill $(head -1 /var/run/ppp-$(basename $PEER).pid)
+ load_profile "$1"
+ kill $(head -1 "/var/run/ppp-$(basename "$PEER").pid")
+}
+
+ppp_query() {
+ "$CONN_DIR/ethernet" query "$@"
+}
+
+ppp_control() {
+ "$CONN_DIR/wireless" control "$@"
+}
+
+ppp_verify() {
+ local INTERFACE="$1"
+ # do nothing
}
-ppp_$1 $2
+ppp_$1 "$2"
exit $?
# vim: set ts=4 et sw=4:
diff --git a/src/connections/wireless b/src/connections/wireless
index 8b43ed1..f316cb7 100644
--- a/src/connections/wireless
+++ b/src/connections/wireless
@@ -1,124 +1,378 @@
#! /bin/bash
+
+##################################
+##
+# /usr/lib/network/connections/wireless
+##
+##################################
+
+. /etc/rc.conf
+. /etc/rc.d/functions
. /usr/lib/network/network
wireless_up() {
- load_profile $1
- . ${SUBR_DIR}/8021x
- . ${SUBR_DIR}/wireless
+ load_profile "$1"
+ [[ -n "$2" ]] && ESSID="$2" # JP: use the literal ESSID (though currently we only interpret wireless-dbus ESSIDs as regexps)
+
+ . "$SUBR_DIR/8021x"
+ . "$SUBR_DIR/wireless_utils"
# Check if interface exists
- if [[ ! -e /sys/class/net/"$INTERFACE" ]]; then
- if ! echo "$INTERFACE"|grep ":"; then
- err_append "interface $INTERFACE does not exist"
+ if [[ ! -e "/sys/class/net/$INTERFACE" ]]; then
+ if ! echo "$INTERFACE" | fgrep -q ":"; then
+ report_fail "Interface $INTERFACE does not exist."
return 1
fi
fi
# Kill any lingering wpa_supplicants.
- stop_wpa $INTERFACE
+ report_debug wireless_up stop_wpa "$INTERFACE"
+ stop_wpa "$INTERFACE"
# Most drivers (mac80211) need mode set before device is brought up
# Drivers generally default to managed, but set this to be sure.
- if [[ "$(iwgetid -sm $INTERFACE)" -ne "Managed" ]]; then
- iwconfig $INTERFACE mode managed
- fi
+ if [[ $(iwgetid -sm "$INTERFACE") -ne Managed ]]; then
+ report_debug wireless_up iwconfig "$INTERFACE" mode managed
+ iwconfig "$INTERFACE" mode managed
+ fi
- ifconfig $INTERFACE up
+ report_debug wireless_up ifup
+ wireless_control "$INTERFACE" up || return 1
+
+ quirk prescan && iwlist "$INTERFACE" scan &> /dev/null # bcm43xx
+
+
+ if quirk preessid; then # ipw3945
+ if [[ -n "$AP" ]]; then # JP: enable use of AP
+ # JP: Since I don't undertand why the else block below is an eval, I'm not sure
+ # if this command also needs to be eval'd
+ iwconfig "$INTERFACE" mode managed ap "$AP"
+ else
+ # JP: I don't understand why this needs to be an eval. What's wrong with just:
+ # iwconfig "$INTERFACE" mode managed essid "$ESSID"
+ eval "iwconfig \"$INTERFACE\" mode managed essid \"$ESSID\""
+ fi
- quirk "prescan" && iwlist $INTERFACE scan &> /dev/null # bcm43xx
- quirk "preessid" && eval "iwconfig $INTERFACE mode managed essid \"$ESSID\"" # ipw3945
+ fi
- if checkyesno ${SCAN:-no}; then
- if ! find_essid $INTERFACE "$ESSID"; then
- err_append "Network not present."
+ if checkyesno "${SCAN:-no}"; then
+ report_debug wireless_up scanning
+ local OLDESSID="$ESSID"
+ if [[ -n "$AP" ]]; then
+ ESSID=$(find_ap "$INTERFACE" "$AP")
+ else
+ ESSID=$(find_essid "$INTERFACE" "$ESSID" "$CONNECTION") # JP: we could have left $3 null for default of treating ESSID as literal
+ # but instead we explicitly pass $CONNECTION
+ fi
+ if [[ $? -gt 0 ]]; then
+ report_fail "Wireless network \"$OLDESSID\" not present."
return 1
fi
fi
# Manually set iwconfig options
- [[ "$IWCONFIG" ]] && iwconfig $INTERFACE $IWCONFIG
+ if [[ -n "$IWCONFIG" ]]; then
+ report_debug wireless_up iwconfig "$INTERFACE" $IWCONFIG
+ iwconfig "$INTERFACE" $IWCONFIG
+ fi
# Set to 'none' if not set
- [[ -z "$SECURITY" ]] && SECURITY="none"
+ [[ -z "$SECURITY" ]] && SECURITY=none
- case $SECURITY in
+ case "$SECURITY" in
wep|none)
# 'none' uses iwconfig like wep. Use sane default if WEP_OPTS=""
- if [[ "$SECURITY" = "wep" ]]; then
- WEP_OPTS="essid \"$ESSID\" key $KEY"
- elif [[ "$SECURITY" = "none" ]]; then
- WEP_OPTS="essid \"$ESSID\""
- fi
+ if [[ -z "$WEP_OPTS" ]]; then
+ if [[ "$SECURITY" = wep ]]; then
+ if [[ -n "$AP" ]]; then
+ WEP_OPTS="ap \"$AP\" key $KEY" # JP: formerly I had "...key open $KEY"; is it correct to omit the 'open'?
+ else
+ WEP_OPTS="essid \"$ESSID\" key $KEY" # JP: formerly I had "...key open $KEY"; is it correct to omit the 'open'?
+ fi
+ else # SECURITY=none
+ if [[ -n "$AP" ]]; then
+ WEP_OPTS="ap \"$AP\""
+ else
+ WEP_OPTS="essid \"$ESSID\""
+ fi
+ fi
+ fi
- quirk "predown" && ifconfig $INTERFACE down # madwifi FS#10585
+ quirk predown && wireless_control "$INTERFACE" forcedown # madwifi FS#10585
- if ! eval iwconfig $INTERFACE $WEP_OPTS; then
- err_append "Could not set wireless configuration."
+ report_debug wireless_up iwconfig "$INTERFACE" $WEP_OPTS
+ # JP: I don't understand why this needs to be an eval. What's wrong with just:
+ # iwconfig "$INTERFACE" $WEP_OPTS
+ if ! eval "iwconfig \"$INTERFACE\" $WEP_OPTS"; then
+ report_fail "Couldn't configure wireless."
return 1
fi
- quirk "predown" && ifconfig $INTERFACE up # madwifi FS#10585
+
+
+ quirk predown && wireless_control "$INTERFACE" up # madwifi FS#10585
- wep_check $INTERFACE $TIMEOUT||return 1
+ report_debug ethernet_up wep_check
+ wep_check "$INTERFACE" "$TIMEOUT" || return 1
;;
+
wpa)
# Quirk for broken drivers... http://bbs.archlinux.org/viewtopic.php?id=36384
- quirk "wpaessid" && eval iwconfig $INTERFACE essid "\"$ESSID\""
+ if quirk wpaessid; then
+ if [[ -n "$AP" ]]; then
+ # JP: Since I don't undertand why the else block below is an eval, I'm not sure
+ # if this command also needs to be eval'd
+ iwconfig "$INTERFACE" ap "$AP"
+ else
+ # JP: I don't understand why this needs to be an eval. What's wrong with just:
+ # iwconfig "$INTERFACE" essid "$ESSID"
+ eval "iwconfig \"$INTERFACE\" essid \"$ESSID\""
+ fi
+ fi
- local WPA_CONF="/tmp/wpa.${1// /}" # substitute spaces out
- echo "ctrl_interface=/var/run/wpa_supplicant" >> $WPA_CONF
- echo "ctrl_interface_group=${WPA_GROUP:-wheel}" >> $WPA_CONF
- chmod 600 $WPA_CONF
+ local WPA_CONF="${TMPDIR:-/tmp}/wpa.${1// /}" # substitute spaces out
+ # make empty tmp dir with correct permissions, rename it
+ rm -rf "$WPA_CONF"
+ mv -f $(mktemp -d) "$WPA_CONF" || return 1
+ echo "ctrl_interface=/var/run/wpa_supplicant" >> "$WPA_CONF/wpa.conf" # we know $WPA_CONF now has no spaces, but it may have other nasty chars, so still needs to be quoted
+ echo "ctrl_interface_group=${WPA_GROUP:-wheel}" >> "$WPA_CONF/wpa.conf"
# Generate configuration
- if [[ "${#KEY}" == "64" ]]; then
- echo -e "network={ \nssid=\"$ESSID\" \npsk=$KEY \n}">> $WPA_CONF
- elif ! echo "$KEY" | wpa_passphrase "$ESSID" >> $WPA_CONF; then
- err_append "Configuration generation failed. $(cat $WPA_CONF)"
+ if [[ "${#KEY}" -eq 64 ]]; then
+ echo -e "network={ \nssid=\"$ESSID\" \npsk=$KEY \n}">> "$WPA_CONF/wpa.conf"
+ # JP: formerly I had { \nssid=\"$ESSID\" \nproto=WPA \nkey_mgmt=WPA-PSK \npsk=$KEY \n}
+ # JP: is what's above better?
+ elif ! echo "$KEY" | wpa_passphrase "$ESSID" >> "$WPA_CONF/wpa.conf"; then
+ report_fail "Couldn't generate WPA configuration."
+ cat "$WPA_CONF/wpa.conf" >&2
return 1
fi
# Connect!
[[ -z "$WPA_OPTS" ]] && WPA_OPTS="-Dwext"
- start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
- if ! wpa_check $INTERFACE $TIMEOUT; then
- stop_wpa $INTERFACE
+ report_debug wireless_up start_wpa "$INTERFACE" "$WPA_CONF/wpa.conf" "$WPA_OPTS"
+ start_wpa "$INTERFACE" "$WPA_CONF/wpa.conf" "$WPA_OPTS" || return 1
+ report_debug wireless_up wpa_check
+ if ! wpa_check "$INTERFACE" "$TIMEOUT"; then
+ stop_wpa "$INTERFACE"
return 1
fi
;;
wpa-config)
- . ${SUBR_DIR}/8021x
+ . "$SUBR_DIR/8021x"
[[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf" # defaults
[[ -z "$WPA_OPTS" ]] && WPA_OPTS="-Dwext"
- start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
- if ! wpa_check $INTERFACE $TIMEOUT; then
- stop_wpa $INTERFACE
+ report_debug wireless_up start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
+ start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS" || return 1
+ report_debug wireless_up wpa_check
+ if ! wpa_check "$INTERFACE" "$TIMEOUT"; then
+ stop_wpa "$INTERFACE"
return 1
fi
;;
esac
- if ! ${CONN_DIR}/ethernet up $1; then
- wireless_down $1 YES
+ if ! "$CONN_DIR/ethernet" up "$1"; then
+ wireless_down "$1" YES
return 1
fi
}
+# wireless_down PROFILE [ LEAVE ifconfig up? default no ]
wireless_down() {
- load_profile $1
- . ${SUBR_DIR}/8021x
- PROFILE=$1 NOETHERNETDOWN=$2
- if ! checkyesno $2; then
- ${CONN_DIR}/ethernet down $1
+ load_profile "$1"
+ . "$SUBR_DIR/8021x"
+ local PROFILE="$1" NOETHERNETDOWN="$2" # JP: made declarations local?? also, why introduce these vars if you're not going to use them?
+ if ! checkyesno "$NOETHERNETDOWN"; then
+ "$CONN_DIR/ethernet" down "$PROFILE"
fi
- stop_wpa $INTERFACE
- [[ "$SECURITY" == "wpa" ]] && rm -f "/tmp/wpa.${1// /}" # remove wpa config
- iwconfig $INTERFACE essid off key off &> /dev/null
- ifconfig $INTERFACE down
+ report_debug wireless_down stop_wpa "$INTERFACE"
+ stop_wpa "$INTERFACE"
+ [[ "$SECURITY" == wpa ]] && rm -rf "/tmp/wpa.${PROFILE// /}" # remove tmp wpa config
+ report_debug wireless_down iwconfig "$INTERFACE" essid off key off
+ iwconfig "$INTERFACE" essid off key off &> /dev/null
+ #wireless_control "$INTERFACE" forcedown # this is now handled in ethernet down, isn't it?
}
-wireless_$1 $2
+# CONNECTION_query $INTERFACE [ profile | enabled (i.e. not rfkill-ed) | active (i.e. ifup'd) | associated | address ] [ "" | "-iproute" ]
+# "query associated" also uses $4=ESSID $5=AP if known
+wireless_query() {
+ local INTERFACE="$1" REQUEST="$2" NEW="$3"
+ #report_debug wireless_query "$@"
+ case "$REQUEST" in
+
+ profile)
+ # return code = 1 if iface is available to be used
+ # return code = 0 if unavailable (disabled, or in use by another profile or by external config)
+ # echo "" | "disabled" | "external" | PROFILE_NAME
+ if [[ ! -f "$STATE_DIR/interfaces/$INTERFACE" ]]; then
+ # wireless interface is up but has no registered profile
+ if ! wireless_query "$INTERFACE" enabled "$NEW"; then
+ wireless_control disable "$INTERFACE" # STATE_DIR/interface should say "disabled" instead
+ # iface should be down if it''s disabled
+ wireless_control "$INTERFACE" down "$NEW"
+ echo "disabled"
+ return 0
+ fi
+ if wireless_query "$INTERFACE" address "$NEW"; then
+ set_iface up "$INTERFACE" external
+ echo "external"
+ return 0
+ fi
+ # no ip address, count as inactive (even if associated)
+ # should we tell iface to de-associate if still associated?
+ # should we ifconfig iface down? no, may be up for a reason
+ return 1
+
+ else # interface is up and thinks it's running a profile
+ . "$STATE_DIR/interfaces/$INTERFACE" # these files should only contain a PROFILE=... statement
+ case "$PROFILE" in
+ external)
+ echo "external"
+ return 0
+ ;;
+ disabled)
+ # iface should be down if it's disabled
+ wireless_control "$INTERFACE" down "$NEW"
+ echo "disabled"
+ return 0
+ ;;
+ *)
+ ( # use subshell to prevent overwriting currently loaded profile
+ . "$STATE_DIR/profiles/$PROFILE"
+ if ! "$CONN_DIR/$CONNECTION" query "$INTERFACE" enabled; then
+ report_warn "INTERFACE $INTERFACE is disabled; no longer being controlled by $PROFILE"
+ set_profile down "$PROFILE"
+ wireless_control disable "$INTERFACE"
+ wireless_control "$INTERFACE" down "$NEW"
+ echo "disabled"
+ exit 0
+ elif ! wireless_query "$INTERFACE" address "$NEW"; then
+ report_warn "INTERFACE $INTERFACE is inactive; no longer being controlled by $PROFILE"
+ set_profile down "$PROFILE"
+ exit 1
+ elif "$CONN_DIR/$CONNECTION" query "$INTERFACE" associated "$NEW" "$ESSID" "$AP"; then
+ echo "$PROFILE" # associated with loaded profile
+ exit 0
+ else
+ report_warn "INTERFACE $INTERFACE no longer being controlled by $PROFILE"
+ set_profile down "$PROFILE"
+ set_iface up "$INTERFACE" external
+ echo "external"
+ exit 0
+ fi
+ )
+ # return $?
+ ;;
+ esac
+ fi
+ ;;
+
+ enabled)
+ local rfkill iftype
+ for rfkill in /sys/class/rfkill/*; do
+ if [[ -e "$rfkill/type" && -e "$rfkill/state" ]]; then
+ iftype=$(cat "$rfkill/type")
+ if [[ "$iftype" == wlan || "$iftype" == "${INTERFACE:0:${#INTERFACE}-1}" ]]; then # JP: don't really know what the range of values for this is
+ # on my machine, the INTERFACE is wlan0 and the type=wlan
+ test $(cat "$rfkill/state") -eq 1 # state is 1 when enabled, 2 when killed
+ return $?
+ fi
+ fi
+ done
+# # JP: this is easier, but I don't know if it can be relied on to stay in place...
+# if [[ -e /sys/class/net/$INTERFACE/device/rfkill/rfkill?/state ]]; then
+# test $(cat /sys/class/net/$INTERFACE/device/rfkill/rfkill?/state) -eq 1
+# return $?
+# fi
+ return 0 # default to enabled
+ ;;
+
+ associated)
+ # assumed to have ip address
+ # return 0: associated with loaded profile
+ # 1: associated with other
+ # 2: still has ip address but unassociated: can this happen?
+ local ESSID="$4" AP="$5"
+ local essid=$(iwgetid "$INTERFACE" -r) ap=$(iwgetid "$INTERFACE" -ra)
+ [[ -z "$ap" ]] && return 2
+ if [[ -n "$AP" ]]; then
+ [[ $(echo "$AP" | tr 'abcdef' 'ABCDEF') == "$ap" ]]
+ return $?
+ fi
+ case "$ESSID" in
+ # [Rr][Oo][Aa][Mm]|[Oo][Pp][Ee][Nn])
+ # return 0
+ # ;;
+ *)
+ if [[ "$NEW" == -iproute ]]; then
+ # JP: ESSID is a regexp; we handle this here instead of in the wireless-dbus script for now
+ expr match "$essid" "^$ESSID\$" >/dev/null
+ return $? # returns true if matched more than 0 chars
+ else
+ [[ "$ESSID" == "$essid" ]]
+ return $?
+ fi
+ ;;
+ esac
+ ;;
+
+ active|address)
+ "$CONN_DIR/ethernet$NEW" query "$INTERFACE" "$REQUEST"
+ ;;
+
+ *) return 1;;
+ esac
+}
+
+# CONNECTION_control $INTERFACE [ up | down | forcedown | enable | disable ] [ "" | "-iproute" ]
+wireless_control() {
+ local INTERFACE="$1" ACTION="$2" NEW="$3"
+ #report_debug wireless_control "$@"
+ case "$ACTION" in
+ enable)
+ [[ $(query_iface "$INTERFACE") == disabled ]] && set_iface "$INTERFACE" down
+ ;;
+ disable)
+ set_iface up "$INTERFACE" disabled
+ ;;
+ up)
+ if [[ "$NEW" = -iproute ]]; then
+ "$CONN_DIR/ethernet-iproute" control "$INTERFACE" "$ACTION"
+ else
+ # JP: same as ethernet control ... up
+ #ifconfig "$INTERFACE" up 2>/dev/null
+ ifconfig "$INTERFACE" up
+ wireless_query "$INTERFACE" active
+ fi
+ ;;
+ down|forcedown)
+ if [[ "$NEW" = -iproute ]]; then
+ "$CONN_DIR/ethernet-iproute" control "$INTERFACE" "$ACTION"
+ else
+ # JP: differs slightly from ethernet control ... down (but I don't know whether the difference is really appropriate, I'm just preserving it from older codebase)
+ ifconfig "$INTERFACE" 0.0.0.0
+ if [[ "$2" = forcedown ]]; then
+ ifconfig "$INTERFACE" down
+ fi
+ fi
+ ;;
+ *) return 1;;
+ esac
+}
+
+wireless_verify() {
+ local INTERFACE="$1"
+ if [[ -d "/sys/class/net/$INTERFACE/phy80211" || -d "/sys/class/net/$INTERFACE/wireless" ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+wireless_$1 "$2" "$3" "$4" "$5" "$6"
exit $?
# vim: set ts=4 et sw=4:
+