Commit 8ccfe971 authored by Jouke Witteveen's avatar Jouke Witteveen
Browse files

Improve cleanup for failed wireless connections (FS#46859)

A generated config file could be left behind.
This occurs for instance when a removable interface is removed when used
or when an interface is blocked by rfkill, but netctl is not instructed
to utilize its rfkill routines.
parent 1823a49c
......@@ -11,6 +11,7 @@ Type=forking
RemainAfterExit=yes
ExecStart=/usr/bin/netctl-auto start %I
ExecStop=/usr/bin/netctl-auto stop %I
ExecStopPost=/usr/bin/netctl-auto clean %I
[Install]
WantedBy=multi-user.target
......@@ -43,10 +43,9 @@ ethernet_up() {
return 1
fi
if ! wpa_wait_until_state "$TimeoutWPA" "$Interface" "ASSOCIATED"; then
if ! wpa_wait_until_completed "$TimeoutWPA" "$Interface" "ASSOCIATED"; then
wpa_stop "$Interface"
bring_interface_down "$Interface"
report_error "WPA Authentication/Association Failed"
return 1
fi
fi
......
......@@ -29,9 +29,11 @@ wireless_up() {
: ${WPAConfigFile:=/etc/wpa_supplicant.conf}
config_file=$WPAConfigFile
else
# Remove any stray configuration files
wpa_destroy_config_file "$Interface"
config_file=$(wpa_make_config_file "$Interface")
if [[ -z $config_file ]]; then
report_error "Could not create a wpa config file for interface '$Interface'"
report_error "Could not create a WPA config file for interface '$Interface'"
return 1
fi
printf "%s\n" "network={" "$(wpa_make_config_block)" "}" >> "$config_file"
......@@ -40,6 +42,9 @@ wireless_up() {
# Start the WPA supplicant
if ! wpa_start "$Interface" "$WPADriver" "$config_file"; then
report_error "The WPA supplicant did not start for interface '$Interface'"
if [[ $Security != "wpa-config" ]]; then
wpa_destroy_config_file "$Interface"
fi
bring_interface_down "$Interface"
return 1
fi
......@@ -47,18 +52,13 @@ wireless_up() {
# Bring interface up after starting wpa_supplicant
# This is important since cards such as iwl3945 do not support
# mode switching when they are already up.
bring_interface_up "$Interface" || return 1
if ! wpa_wait_until_state "$TimeoutWPA" "$Interface" "COMPLETED"; then
report_error "WPA association/authentication failed for interface '$Interface'"
report_debug "WPA state for interface '$Interface': $(wpa_get_state "$Interface")"
wpa_stop "$Interface"
bring_interface_down "$Interface"
return 1
fi
if ! ip_set; then
if ! bring_interface_up "$Interface" ||
! wpa_wait_until_completed "$TimeoutWPA" "$Interface" ||
! ip_set; then
wpa_stop "$Interface"
if [[ $Security != "wpa-config" ]]; then
wpa_destroy_config_file "$Interface"
fi
bring_interface_down "$Interface"
return 1
fi
......@@ -68,6 +68,8 @@ wireless_down() {
ip_unset
if [[ $Security == "wpa-config" ]]; then
: ${WPAConfigFile:=/etc/wpa_supplicant.conf}
else
wpa_destroy_config_file "$Interface"
fi
wpa_stop "$Interface"
bring_interface_down "$Interface" || return 1
......
......@@ -22,13 +22,13 @@ wpa_call() {
do_debug wpa_cli "${args[@]}" "$@"
}
## Check if an instance of the wpa supplicant is active on an interface
## Check if an instance of the WPA supplicant is active on an interface
# $1: interface name
wpa_is_active() {
[[ $(wpa_call "$1" ping 2> /dev/null) == "PONG" ]]
}
## Retrieves the state of an instance of the wpa supplicant
## Retrieve the state of an instance of the WPA supplicant
## Displays one of: DISCONNECTED, INTERFACE_DISABLED, INACTIVE, SCANNING,
## AUTHENTICATING, ASSOCIATING, ASSOCIATED, 4WAY_HANDSHAKE,
## GROUP_HANDSHAKE, COMPLETED
......@@ -39,7 +39,7 @@ wpa_get_state() {
echo "${state#wpa_state=}"
}
## Waits until the wpa supplicant reaches a listed state
## Wait until the WPA supplicant reaches a listed state
# $1: timeout
# $2: interface name
# $3...: accepted states
......@@ -49,7 +49,7 @@ wpa_wait_until_state() {
'in_array "$(wpa_get_state "$interface")" "${states[@]}"'
}
## Waits while the wpa supplicant is in a listed state
## Wait while the WPA supplicant is in a listed state
# $1: timeout
# $2: interface name
# $3...: rejected states
......@@ -59,7 +59,21 @@ wpa_wait_while_state() {
'! in_array "$(wpa_get_state "$interface")" "${states[@]}"'
}
## Start an instance of the wpa supplicant
## Wait for the WPA supplicant to finish association and authentication
# $1: timeout
# $2: interface name
# $3...: additional accepted states
wpa_wait_until_completed() {
local timeout=$1 interface=$2
shift 2
if ! wpa_wait_until_state "$timeout" "$interface" "COMPLETED" "$@"; then
report_error "WPA association/authentication failed for interface '$interface'"
report_debug "WPA state for interface '$interface': $(wpa_get_state "$interface")"
return 1
fi
}
## Start an instance of the WPA supplicant
# $1: interface name
# $2: interface driver(s)
# $3: configuration file
......@@ -82,30 +96,22 @@ wpa_start() {
"$configuration" $WPAOptions >&2
# Wait up to one second for the pid file to appear
if ! timeout_wait 1 '[[ -f $pidfile ]]'; then
# Remove the configuration file if it was generated
configuration="$STATE_DIR/wpa_supplicant-$interface.conf"
[[ -f $configuration && -O $configuration ]] && rm -f "$configuration"
return 1
fi
timeout_wait 1 '[[ -f $pidfile ]]'
}
## Stop an instance of the wpa supplicant
## Stop an instance of the WPA supplicant
# $1: interface name
wpa_stop() {
local interface=$1 config_file="$STATE_DIR/wpa_supplicant-$1.conf"
local pidfile="/run/wpa_supplicant-$interface.pid"
local interface=$1 pidfile="/run/wpa_supplicant-$1.pid"
# We need this as long as wpa_cli has a different default than netctl
if [[ -z $WPA_CTRL_DIR && -z $WPAConfigFile ]]; then
WPA_CTRL_DIR="/run/wpa_supplicant"
fi
# Done if wpa_supplicant is already terminated for this interface
[[ -z $WPA_CTRL_DIR || -e "$WPA_CTRL_DIR/$interface" ]] || return
[[ -z $WPA_CTRL_DIR || -e "$WPA_CTRL_DIR/$interface" ]] || return 0
wpa_call "$interface" terminate > /dev/null
[[ -f $config_file && -O $config_file ]] && rm -f "$config_file"
# Wait up to one second for the pid file to be removed
if ! timeout_wait 1 '[[ ! -f $pidfile ]]'; then
kill "$(< "$pidfile")" &> /dev/null
......@@ -173,7 +179,7 @@ wpa_quote() {
fi
}
## Unquotes a string, i.e. returned from wpa_cli
## Unquote a string, i.e. returned from wpa_cli
## Quoted: "string" -> string
## Non-Quoted: string -> string
## Hex: 737472696e67 -> string
......@@ -258,5 +264,14 @@ wpa_make_config_block() {
[[ $Priority ]] && echo "priority=$Priority"
}
## Remove a configuration file for wpa_supplicant
# $1: interface name
wpa_destroy_config_file() {
local config_file="$STATE_DIR/wpa_supplicant-$1.conf"
if [[ -f $config_file && -O $config_file ]]; then
do_debug rm -f "$config_file"
fi
}
# vim: ft=sh ts=4 et sw=4:
......@@ -60,7 +60,7 @@ list_wpa_profiles() {
done
}
## Get WPA supplicant network id and interface for the given profile
## Get the WPA supplicant network id and interface for the given profile
## Output format: INTERFACE ID
# $1: profile name
get_wpa_network_id() {
......@@ -76,7 +76,7 @@ get_wpa_network_id() {
return 1
}
## Enable or disable profiles in WPA supplicant
## Enable or disable profiles in the WPA supplicant
# $1: profile action: "enable", "disable", "enable-all" or "disable-all"
# $2: profile name if action is "enable" or "disable"
profile_enable_disable() {
......@@ -142,9 +142,7 @@ switch_to() {
# select_network will disable all other networks on that interface
wpa_call "$interface" select_network "$id" >/dev/null
if ! wpa_wait_until_state "$timeout" "$interface" "COMPLETED"; then
report_error "WPA association/authentication failed for interface '$interface'"
fi
wpa_wait_until_completed "$timeout" "$interface"
reenable_networks
}
......@@ -208,7 +206,6 @@ start() {
rf_enable "$interface" "$RFKill" || return 1
fi
local wpa_conf
if ! wpa_conf=$(wpa_make_config_file "$interface"); then
exit_error "Could not create the configuration file for interface '$interface'"
......@@ -240,10 +237,11 @@ start() {
wpa_stop "$interface"
bring_interface_down "$interface"
fi
# Systemd executes cleanup on failure
return 1
}
## Stop wpa_supplicant and wpa_actiond
## Stop the WPA supplicant and wpa_actiond
# $1: interface
stop() {
local interface="$1"
......@@ -256,6 +254,12 @@ stop() {
return 0
}
## Remove WPA supplicant configuration files
# $1: interface
clean() {
wpa_destroy_config_file "$1"
}
case $# in
1)
......@@ -277,9 +281,9 @@ case $# in
profile_enable_disable "$1" "$2";;
switch-to|is-active|is-enabled)
"${1//-/_}" "$2";;
start|stop)
start|stop|clean)
if [[ -t 0 ]]; then
exit_error "Use 'systemctl $1 netctl-auto@$2' to $1 netctl-auto."
exit_error "Use 'systemctl ${1/clean/stop} netctl-auto@$2' to $1 netctl-auto."
fi
ensure_root "$(basename "$0")"
load_interface_config "$2"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment