Commit 8773d7f0 authored by Jouke Witteveen's avatar Jouke Witteveen
Browse files

More uniform profile loading and filtering

Hooks and interface scripts are now sourced more systematically.
Settings of wireless profiles that depend on hooks are now picked up
correctly by netctl-auto.

Suggested by: Vitor Sakaguti <vis@tutao.de>
parent 9b70046f
...@@ -14,11 +14,10 @@ case "$2" in ...@@ -14,11 +14,10 @@ case "$2" in
printf '%s' "$profile" > "$PROFILE_FILE" printf '%s' "$profile" > "$PROFILE_FILE"
exit 0 exit 0
fi fi
done < <(list_profiles | while IFS= read -r profile; do done < <(filter_profiles "$1" ethernet | while IFS= read -r profile; do
report_debug "Examining profile '$profile'" report_debug "Examining profile '$profile'"
( (
source "$PROFILE_DIR/$profile" > /dev/null load_profile "$profile" > /dev/null
[[ $Interface == "$1" && $Connection == "ethernet" ]] || exit
# Prioritize dhcp based profiles as they can outright fail, whereas # Prioritize dhcp based profiles as they can outright fail, whereas
# it is difficult to tell if a profile with a static address fails # it is difficult to tell if a profile with a static address fails
if [[ $IP == "dhcp" || $IP6 == dhcp* ]]; then if [[ $IP == "dhcp" || $IP6 == dhcp* ]]; then
......
#! /bin/bash #! /bin/bash
. /usr/lib/netctl/globals . /usr/lib/netctl/globals
. "$SUBR_DIR/interface"
. "$SUBR_DIR/ip" . "$SUBR_DIR/ip"
export INTERFACE="$1" export INTERFACE="$1"
...@@ -11,7 +10,6 @@ PROFILE_FILE="$STATE_DIR/netctl-auto-$INTERFACE.profile" ...@@ -11,7 +10,6 @@ PROFILE_FILE="$STATE_DIR/netctl-auto-$INTERFACE.profile"
case $ACTION in case $ACTION in
CONNECTED) CONNECTED)
load_profile "$WPA_ID_STR" load_profile "$WPA_ID_STR"
load_interface_config "$INTERFACE"
DhcpcdOptions+=" -K -L" DhcpcdOptions+=" -K -L"
ip_set || exit 1 ip_set || exit 1
mkdir -p "$(dirname "$PROFILE_FILE")" mkdir -p "$(dirname "$PROFILE_FILE")"
...@@ -26,7 +24,6 @@ case $ACTION in ...@@ -26,7 +24,6 @@ case $ACTION in
DISCONNECTED) DISCONNECTED)
if [[ -s "$PROFILE_FILE" ]]; then if [[ -s "$PROFILE_FILE" ]]; then
load_profile "$(< "$PROFILE_FILE")" load_profile "$(< "$PROFILE_FILE")"
load_interface_config "$INTERFACE"
rm -f "$PROFILE_FILE" rm -f "$PROFILE_FILE"
# Sandbox the eval # Sandbox the eval
if ! ( do_debug eval "$ExecDownPre" ); then if ! ( do_debug eval "$ExecDownPre" ); then
......
...@@ -103,41 +103,71 @@ timeout_wait() { ...@@ -103,41 +103,71 @@ timeout_wait() {
### Profile management ### Profile management
## List all acceptable profiles names separated by newlines ## Load all available hooks
list_profiles() { load_hooks() {
# Follow aliases with -L, skip forbidden/reserved names local hook
find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n' while IFS= read -r hook; do
source "$hook"
done < <(find -L "$PROFILE_DIR/hooks" -maxdepth 1 -type f -executable -not -name '.*' -not -name '*~' -not -name $'*\n*' | sort)
} }
## Exit if a profile file is not syntactically correct ## Load interface configuration, if present
# $1: profile name # $1: interface name
verify_profile() { load_interface_config() {
/bin/bash -n "$PROFILE_DIR/$1" || exit 1 local config_file="$PROFILE_DIR/interfaces/$1"
if [[ -x $config_file ]]; then
source "$config_file"
fi
} }
## Sources all hooks and a profile (but no interface configuration) ## Sources all hooks and a profile (but no interface configuration)
# $1: profile name # $1: profile name
load_profile() { load_profile() {
local hook
# Expose the profile name # Expose the profile name
Profile=$1 Profile=$1
if [[ -z $Profile || ! -r "$PROFILE_DIR/$Profile" ]]; then if [[ -z $Profile || ! -r "$PROFILE_DIR/$Profile" ]]; then
exit_error "Profile '$Profile' does not exist or is not readable" exit_error "Profile '$Profile' does not exist or is not readable"
fi fi
while IFS= read -r hook; do load_hooks
source "$hook"
done < <(find -L "$PROFILE_DIR/hooks" -maxdepth 1 -type f -executable -not -name '.*' -not -name '*~' -not -name $'*\n*' | sort -u)
unset hook
source "$PROFILE_DIR/$Profile" source "$PROFILE_DIR/$Profile"
if [[ -z $Interface ]]; then if [[ -z $Interface ]]; then
exit_error "Profile '$Profile' does not specify an interface" exit_error "Profile '$Profile' does not specify an interface"
fi fi
load_interface_config "$Interface"
if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then
exit_error "Profile '$Profile' does not specify a valid connection" exit_error "Profile '$Profile' does not specify a valid connection"
fi fi
source "$SUBR_DIR/connections/$Connection" source "$SUBR_DIR/connections/$Connection"
} }
## List all acceptable profiles names separated by newlines
list_profiles() {
# Follow aliases with -L, skip forbidden/reserved names
find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n'
}
## List names of profiles for a given interface and/or connection
# $1: interface (optional)
# $2: connection (optional)
filter_profiles() {
list_profiles | while IFS= read -r Profile; do
if (
source "$PROFILE_DIR/$Profile" &> /dev/null
[[ $Interface && ( -z $1 || $1 == "$Interface" ) ]] || exit
load_interface_config "$Interface" > /dev/null
[[ $Connection && ( -z $2 || $2 == "$Connection" ) ]] || exit
); then
printf '%s\n' "$Profile"
fi
done
}
## Exit if a profile file is not syntactically correct
# $1: profile name
verify_profile() {
/bin/bash -n "$PROFILE_DIR/$1" || exit 1
}
## Wrapper around systemctl converting profile names to unit names ## Wrapper around systemctl converting profile names to unit names
# $1: systemctl command # $1: systemctl command
# $2...: profile names # $2...: profile names
......
## /usr/lib/netctl/globals needs to be sourced before this file ## /usr/lib/netctl/globals needs to be sourced before this file
## Load interface configuration, if present
# $1: interface name
load_interface_config() {
local config_file="$PROFILE_DIR/interfaces/$1"
if [[ -x $config_file ]]; then
source "$config_file"
fi
}
## Check if a string represents a network interface ## Check if a string represents a network interface
# $1: potential interface name # $1: potential interface name
is_interface() { is_interface() {
......
...@@ -88,7 +88,6 @@ elif [[ $# -eq 2 && $1 == @(start|stop) ]]; then ...@@ -88,7 +88,6 @@ elif [[ $# -eq 2 && $1 == @(start|stop) ]]; then
# Expose the command # Expose the command
Command=$1 Command=$1
load_profile "$2" load_profile "$2"
load_interface_config "$Interface"
"network_$1" "network_$1"
else else
exit_error "Usage: $0 {start|stop|wait-online} [profile]" exit_error "Usage: $0 {start|stop|wait-online} [profile]"
......
...@@ -211,12 +211,10 @@ start() { ...@@ -211,12 +211,10 @@ start() {
# Disable p2p to prevent wpa_supplicant from creating another control interface # Disable p2p to prevent wpa_supplicant from creating another control interface
echo "p2p_disabled=1" >> "$WPAConfigFile" echo "p2p_disabled=1" >> "$WPAConfigFile"
local profile filter_profiles "$interface" wireless | while IFS= read -r profile; do
list_profiles | while IFS= read -r profile; do
report_debug "Examining profile '$profile'" report_debug "Examining profile '$profile'"
( (
source "$PROFILE_DIR/$profile" load_profile "$profile"
[[ $Interface == "$interface" && $Connection == "wireless" ]] || exit
is_yes "${ExcludeAuto:-no}" && exit is_yes "${ExcludeAuto:-no}" && exit
# Set default and exclude wpa-config as it does not fit this scheme # Set default and exclude wpa-config as it does not fit this scheme
[[ ${Security:=none} != "wpa-config" ]] || exit [[ ${Security:=none} != "wpa-config" ]] || exit
......
...@@ -71,16 +71,11 @@ stop_all() { ...@@ -71,16 +71,11 @@ stop_all() {
} }
switch_to() { switch_to() {
cd "$PROFILE_DIR" Interface=$(. "$PROFILE_DIR/$1" >/dev/null; printf '%s' "$Interface")
# We assume interface names are not quoted if [[ -z $Interface ]]; then
# Using read removes leading whitespace
read InterfaceLine < \
<(grep -om1 '^[[:space:]]*Interface=[[:alnum:]:._-]\+' "$1")
if [[ -z $InterfaceLine ]]; then
exit_error "Profile '$1' does not specify an interface" exit_error "Profile '$1' does not specify an interface"
fi fi
mapfile -t AllProfiles < <(list_profiles) mapfile -t Profiles < <(filter_profiles "$Interface")
mapfile -t Profiles < <(grep -Fl "$InterfaceLine" "${AllProfiles[@]}")
if (( ${#Profiles[@]} )); then if (( ${#Profiles[@]} )); then
do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2) do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2)
fi fi
......
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