[arch-projects] [netctl][PATCH] More uniform profile loading and filtering
Jouke Witteveen
j.witteveen at gmail.com
Fri May 7 13:01:33 UTC 2021
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 at tutao.de>
---
Inspired by a report on GitHub:
https://github.com/joukewitteveen/netctl/issues/185
src/ifplugd.action | 5 ++--
src/lib/auto.action | 3 ---
src/lib/globals | 56 ++++++++++++++++++++++++++++++++++-----------
src/lib/interface | 9 --------
src/lib/network | 1 -
src/netctl-auto | 6 ++---
src/netctl.in | 11 +++------
7 files changed, 50 insertions(+), 41 deletions(-)
diff --git a/src/ifplugd.action b/src/ifplugd.action
index c1f0e7d..0cebb34 100755
--- a/src/ifplugd.action
+++ b/src/ifplugd.action
@@ -14,11 +14,10 @@ case "$2" in
printf '%s' "$profile" > "$PROFILE_FILE"
exit 0
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'"
(
- source "$PROFILE_DIR/$profile" > /dev/null
- [[ $Interface == "$1" && $Connection == "ethernet" ]] || exit
+ load_profile "$profile" > /dev/null
# Prioritize dhcp based profiles as they can outright fail, whereas
# it is difficult to tell if a profile with a static address fails
if [[ $IP == "dhcp" || $IP6 == dhcp* ]]; then
diff --git a/src/lib/auto.action b/src/lib/auto.action
index 6c13651..717d205 100755
--- a/src/lib/auto.action
+++ b/src/lib/auto.action
@@ -1,7 +1,6 @@
#! /bin/bash
. /usr/lib/netctl/globals
-. "$SUBR_DIR/interface"
. "$SUBR_DIR/ip"
export INTERFACE="$1"
@@ -11,7 +10,6 @@ PROFILE_FILE="$STATE_DIR/netctl-auto-$INTERFACE.profile"
case $ACTION in
CONNECTED)
load_profile "$WPA_ID_STR"
- load_interface_config "$INTERFACE"
DhcpcdOptions+=" -K -L"
ip_set || exit 1
mkdir -p "$(dirname "$PROFILE_FILE")"
@@ -26,7 +24,6 @@ case $ACTION in
DISCONNECTED)
if [[ -s "$PROFILE_FILE" ]]; then
load_profile "$(< "$PROFILE_FILE")"
- load_interface_config "$INTERFACE"
rm -f "$PROFILE_FILE"
# Sandbox the eval
if ! ( do_debug eval "$ExecDownPre" ); then
diff --git a/src/lib/globals b/src/lib/globals
index 32a1802..3d2c50d 100644
--- a/src/lib/globals
+++ b/src/lib/globals
@@ -103,41 +103,71 @@ timeout_wait() {
### Profile management
-## 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'
+## Load all available hooks
+load_hooks() {
+ local hook
+ 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
-# $1: profile name
-verify_profile() {
- /bin/bash -n "$PROFILE_DIR/$1" || exit 1
+## 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
}
## Sources all hooks and a profile (but no interface configuration)
# $1: profile name
load_profile() {
- local hook
# Expose the profile name
Profile=$1
if [[ -z $Profile || ! -r "$PROFILE_DIR/$Profile" ]]; then
exit_error "Profile '$Profile' does not exist or is not readable"
fi
- 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 -u)
- unset hook
+ load_hooks
source "$PROFILE_DIR/$Profile"
if [[ -z $Interface ]]; then
exit_error "Profile '$Profile' does not specify an interface"
fi
+ load_interface_config "$Interface"
if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then
exit_error "Profile '$Profile' does not specify a valid connection"
fi
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" || exit
+ [[ -z $1 || $1 == "$Interface" ]] || exit
+ load_interface_config "$Interface"
+ [[ -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
# $1: systemctl command
# $2...: profile names
diff --git a/src/lib/interface b/src/lib/interface
index 1a51c07..8504191 100644
--- a/src/lib/interface
+++ b/src/lib/interface
@@ -1,15 +1,6 @@
## /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
# $1: potential interface name
is_interface() {
diff --git a/src/lib/network b/src/lib/network
index b6926e3..cb79b77 100755
--- a/src/lib/network
+++ b/src/lib/network
@@ -88,7 +88,6 @@ elif [[ $# -eq 2 && $1 == @(start|stop) ]]; then
# Expose the command
Command=$1
load_profile "$2"
- load_interface_config "$Interface"
"network_$1"
else
exit_error "Usage: $0 {start|stop|wait-online} [profile]"
diff --git a/src/netctl-auto b/src/netctl-auto
index ec3f7a2..720949e 100755
--- a/src/netctl-auto
+++ b/src/netctl-auto
@@ -211,12 +211,10 @@ start() {
# Disable p2p to prevent wpa_supplicant from creating another control interface
echo "p2p_disabled=1" >> "$WPAConfigFile"
- local profile
- list_profiles | while IFS= read -r profile; do
+ filter_profiles "$interface" wireless | while IFS= read -r profile; do
report_debug "Examining profile '$profile'"
(
- source "$PROFILE_DIR/$profile"
- [[ $Interface == "$interface" && $Connection == "wireless" ]] || exit
+ load_profile "$profile"
is_yes "${ExcludeAuto:-no}" && exit
# Set default and exclude wpa-config as it does not fit this scheme
[[ ${Security:=none} != "wpa-config" ]] || exit
diff --git a/src/netctl.in b/src/netctl.in
index 929eb1e..3a96f12 100644
--- a/src/netctl.in
+++ b/src/netctl.in
@@ -71,16 +71,11 @@ stop_all() {
}
switch_to() {
- cd "$PROFILE_DIR"
- # We assume interface names are not quoted
- # Using read removes leading whitespace
- read InterfaceLine < \
- <(grep -om1 '^[[:space:]]*Interface=[[:alnum:]:._-]\+' "$1")
- if [[ -z $InterfaceLine ]]; then
+ Interface=$(. "$PROFILE_DIR/$1" >/dev/null; printf '%s' "$Interface")
+ if [[ -z $Interface ]]; then
exit_error "Profile '$1' does not specify an interface"
fi
- mapfile -t AllProfiles < <(list_profiles)
- mapfile -t Profiles < <(grep -Fl "$InterfaceLine" "${AllProfiles[@]}")
+ mapfile -t Profiles < <(filter_profiles "$Interface")
if (( ${#Profiles[@]} )); then
do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2)
fi
--
2.31.1
More information about the arch-projects
mailing list