summaryrefslogtreecommitdiffstats
path: root/src/lib/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/network')
-rwxr-xr-x[-rw-r--r--]src/lib/network419
1 files changed, 73 insertions, 346 deletions
diff --git a/src/lib/network b/src/lib/network
index 1aa384c..1117737 100644..100755
--- a/src/lib/network
+++ b/src/lib/network
@@ -1,368 +1,95 @@
-### Globals
-. /usr/lib/network/globals
-# will load hooks
-
-## Loads a profile.
-# $1: profile name
-load_profile()
-{
- unset ROUTES
- [[ -z "$1" ]] && return 1
- if [[ ! -f "$PROFILE_DIR/$1" ]]; then
- report_err "Profile \"$1\" does not exist"
- return 1
- fi
- report_debug "Loading profile $1"
- INTERFACE=$(. "$PROFILE_DIR/$1"; echo "$INTERFACE")
- report_debug "Configuring interface $INTERFACE"
- if [[ -z "$INTERFACE" ]]; then
- report_err "Profile missing an interface to configure"
- return 1
- fi
- if [[ -f "$IFACE_DIR/$INTERFACE" ]]; then
- report_debug "Interface level configuration enabled: $IFACE_DIR/$INTERFACE"
- . "$IFACE_DIR/$INTERFACE"
- fi
- . "$PROFILE_DIR/$1" # we want profile settings to override, so need to source profile again
- if [[ ! -f "$CONN_DIR/$CONNECTION" ]]; then
- report_err "$CONNECTION is not a valid connection, check spelling or look at examples"
- return 1
- fi
-}
-
-##################
-# Profile up/down
-##################
-
-## Take all registered profiles down.
-all_down()
-{
- find "$STATE_DIR/profiles/" -maxdepth 1 -type f -printf '%f\n' \
- | while read prof; do
- profile_down "$prof"
- done
-}
+#! /bin/bash
-## Create the state dir and sub directories if they don't already exist.
-check_make_state_dir()
-{
- [[ ! -d "$STATE_DIR" ]] && mkdir -p "$STATE_DIR"/{interfaces,profiles}
- for d in interfaces profiles suspend; do
- [[ ! -d "$STATE_DIR/$d" ]] && mkdir "$STATE_DIR/$d"
- done
-}
+. /usr/lib/network/globals
-## Save the list of running profiles and take them down if needed
-# $1: interface name or "all"
-# $2: take associated profiles down (optional, default="yes")
-interface_suspend()
-{
- report_debug interface_suspend "$@"
- check_make_state_dir
- find "$STATE_DIR/profiles/" -maxdepth 1 -type f -printf '%f\n' \
- | while read prof; do
- # the pipe to "while read" will create a subshell
- INTERFACE=$(. "$STATE_DIR/profiles/$prof"; echo "$INTERFACE")
- if [[ "$1" == all || "$1" == "$INTERFACE" ]]; then
- report_notice "suspending interface $INTERFACE with profile $prof"
- cp "$STATE_DIR/profiles/$prof" "$STATE_DIR/suspend/"
- if checkyesno "${2:-yes}"; then
- profile_down "$prof"
- fi
- fi
- done
-}
-
-## Save the list of all running profiles and take them down
-all_suspend() {
- interface_suspend all
+## Check if a string represents a network interface
+# $1: potential interface name
+is_interface() {
+ # Strip any old school alias specifier
+ [[ -d "/sys/class/net/${1%%:?*}" ]]
}
-## Restore saved profiles (for resume purposes).
-# $@: a list of interfaces not to resume (e.g., because they're disabled)
-all_resume()
-{
- report_debug all_resume "$@"
- find "$STATE_DIR/suspend/" -maxdepth 1 -type f -printf '%f\n' \
- | while read prof; do
- # the pipe to "while read" will create a subshell
- INTERFACE=$(. "$STATE_DIR/suspend/$prof"; echo "$INTERFACE")
- if [[ $# -eq 0 || ! " $* " =~ " $INTERFACE " ]]; then
- report_notice "resuming interface $INTERFACE with profile $prof"
- profile_up "$prof"
- rm -f "$STATE_DIR/suspend/$prof" # if profile_up succeeds, it will have already removed this
- fi
- done
+## Check if an interface is up
+# $1: interface name
+interface_is_up() {
+ local flags
+ read flags < "/sys/class/net/${1%%:?*}/flags"
+ # IFF_UP is defined as 0x1 in linux/if.h
+ (( flags & 0x1 ))
}
-## Puts up a profile.
-# $1: the profile name
-profile_up()
-{
- (
- # Keep inside subshell so that options from one profile don't cross to others
- # exit 1 used in a subshell is effectively exiting a new process
- check_make_state_dir
-
- local status PROFILE="$1" # save PROFILE in a variable so that it's available to PRE_UP/POST_DOWN etc hooks
-
- load_profile "$PROFILE" || exit 1
-
- if check_profile "$PROFILE"; then
- report_err "$PROFILE already connected"
+## Activate an interface
+# $1: interface name
+bring_interface_up() {
+ local interface=$1
+ ip link set dev "$interface" up &>/dev/null
+ timeout_wait "${TimeoutUp:-5}" 'interface_is_up "$interface"'
+}
+
+## Deactivate an interface
+# $1: interface name
+bring_interface_down() {
+ local interface=$1
+ ip addr flush dev "$interface" &>/dev/null
+ ip link set dev "$interface" down &>/dev/null
+ # We reuse the up timeout (down normally is faster)
+ timeout_wait "${TimeoutUp:-5}" '! interface_is_up "$interface"'
+}
+
+
+if [[ $# -ne 2 || $1 != @(start|stop) ]]; then
+ exit_error "Usage: $0 {start|stop} <profile>"
+fi
+ensure_root netctl
+# Ensure we are not in a transient directory
+cd /
+
+# Expose the profile name
+Profile=$2
+load_profile "$Profile"
+source "$CONN_DIR/$Connection"
+case $1 in
+ start)
+ report_notice "Starting network profile '$Profile'..."
+ if is_interface "$Interface" && interface_is_up "$Interface" && \
+ ! is_yes "${ForceConnect:-no}"; then
+ report_error "The interface of network profile '$Profile' is already up"
exit 1
fi
-
- # EXCLUSIVE, network.d/profile: Individual profile is mutually exclusive
- if checkyesno "$EXCLUSIVE"; then
- all_down
- fi
-
- report_try "$PROFILE up"
-
- status=$(check_iface "$INTERFACE")
- report_debug "status reported to profile_up as: $status"
- case "$status" in
- external)
- report_fail "Interface $INTERFACE externally controlled"
- exit 1
- ;;
- disabled)
- report_fail "Interface $INTERFACE is disabled"
- exit 1
- ;;
- "")
- ;;
- *)
- if checkyesno "$CHECK"; then
- report_fail "Interface $INTERFACE already in use"
- exit 1
-
- # not necessary to sandbox this call or reload PROFILE afterwards
- elif ! interface_down "$INTERFACE"; then
- report_fail
- exit 1
- fi
- ;;
- esac
-
- if ! ( eval $PRE_UP ); then # JP: sandbox the eval so variables don't bleed into current function
- report_debug profile_up "PRE_UP failed"
- report_fail
+ if ! "${Connection}_up"; then
+ report_error "Failed to bring the network up for profile '$Profile'"
exit 1
fi
-
- if ! "$CONN_DIR/$CONNECTION" up "$PROFILE"; then
- report_debug profile_up "connect failed"
- report_fail
- # "$CONN_DIR/$CONNECTION" down "$PROFILE" # JP: should we do this to make sure?
+ # JP: sandbox the eval
+ if ! ( eval $ExecUpPost ); then
+ report_error "ExecUpPost failed for network profile '$Profile'"
+ # Failing ExecUpPost will take the connection down
+ "${Connection}_down"
exit 1
fi
-
- if ! ( eval $POST_UP ); then # JP: sandbox the eval
- report_debug profile_up "POST_UP failed"
- report_fail
- # failing POST_UP will take interface down
- "$CONN_DIR/$CONNECTION" down "$PROFILE"
+ report_notice "Started network profile '$Profile'"
+ ;;
+ stop)
+ report_notice "Stopping network profile '$Profile'..."
+ # JP: sandbox the eval
+ if ! ( eval $ExecDownPre ); then
+ report_error "ExecDownPre failed for network profile '$Profile'"
+ # Failing ExecDownPre will leave the profile active
exit 1
fi
-
- set_profile up "$PROFILE"
- unset EXCLUSIVE
-
- # 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
- INTERFACE=$(. "$STATE_DIR/suspend/$prof"; echo "$INTERFACE")
- if [[ "$iface" == "$INTERFACE" ]]; then
- rm "$STATE_DIR/suspend/$prof"
- fi
- done
-
- report_success
- ); return $?
-}
-
-## Puts a profile down.
-# $1: the profile name
-profile_down()
-{
- (
- check_make_state_dir
-
- local status PROFILE="$1" # save PROFILE in a variable so that it's available to PRE_UP/POST_DOWN etc hooks
-
- load_profile "$PROFILE" || exit 1
-
- status=$(check_iface "$INTERFACE")
- report_debug "status reported to profile_down as: $status"
-
- if [[ "$status" != "$PROFILE" ]]; then
- # if interface not available to be controlled by netcfg, then
- # any profiles should have been removed by check_iface
- # else we get here if another profile is running
- report_err "Profile not connected"
+ if ! "${Connection}_down"; then
+ report_error "Failed to bring the network down for profile '$Profile'"
exit 1
fi
-
- report_try "$PROFILE down"
- if [[ "$(check_iface "$INTERFACE")" == "external" ]]; then
- report_fail "$interface was connected by another application"
+ if is_interface "$Interface" && interface_is_up "$Interface" && \
+ ! is_yes "${ForceConnect:-no}"; then
+ report_error "The interface of network profile '$Profile' did not go down"
exit 1
fi
+ report_notice "Stopped network profile '$Profile'"
+ ;;
+esac
- if ! ( eval $PRE_DOWN ); then # JP: sandbox the eval
- report_debug profile_down "PRE_DOWN failed"
- # true # JP: did we want failing PRE_DOWN to leave the profile active?
- report_fail
- exit 1
- fi
-
- if ! "$CONN_DIR/$CONNECTION" down "$PROFILE"; then
- report_debug profile_up "disconnect failed"
- report_fail
- exit 1
- fi
-
- if ! ( eval $POST_DOWN ); then # JP: sandbox the eval
- report_debug profile_down "POST_DOWN failed"
- report_fail
- exit 1
- fi
-
- set_profile down "$PROFILE"
- report_success
- ); return $?
-}
-
-# interface_down interface
-# take interface down
-#
-interface_down()
-{
- local profile=$(check_iface "$1")
- case "$profile" in
- ""|disabled) return 0 ;;
- external) return 1 ;;
- *) profile_down "$profile" ;;
- esac
-}
-
-# interface_reconnect interface
-# reconnects the profile active on interface
-interface_reconnect()
-{
- local profile=$(check_iface "$1")
- case "$profile" in
- ""|disabled|external)
- return 1
- ;;
- *)
- profile_down "$profile"
- profile_up "$profile"
- ;;
- esac
-}
-
-##
-# check_iface interface
-# Return 0 if interface unavailable (in use by a profile or externally, or disabled)
-# Return 1 if interface down and available to be used
-#
-check_iface() {
- if [[ -f "$STATE_DIR/interfaces/$1" ]]; then
- cat "$STATE_DIR/interfaces/$1"
- return 0
- else
- return 1
- fi
-}
-
-# list_profiles
-# Outputs a list of all profiles
-list_profiles() {
- # JP: follow aliases with -L, also skip profiles that start with '.' or end with '~' or '.conf' (so profile.conf can be the wpa.conf file for profile)
- find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '*~' -not -name '*.conf' -not -name '.*' -printf "%f\n"
-}
-
-# check_profile profile
-# Return 0 if profile registered as being up
-# Return 1 if profile not registered
-#
-check_profile() {
- [[ -f "$STATE_DIR/profiles/$1" && ! -f "$STATE_DIR/suspend/$1" ]] && return 0
- return 1
-}
-
-### Status setting functions
-##
-# set_profile up/down profile
-# Set profile state, either up or down
-#
-set_profile() {
- local INTERFACE
- if [[ "$1" == "up" ]]; then
- INTERFACE=$(. "$PROFILE_DIR/$2"; echo "$INTERFACE")
- cp "$PROFILE_DIR/$2" "$STATE_DIR/profiles/"
- set_iface up "$INTERFACE" "$2"
- elif [[ "$1" == "down" && -f "$STATE_DIR/profiles/$2" ]]; then # JP: skip if profile not already up
- INTERFACE=$(. "$STATE_DIR/profiles/$2"; echo "$INTERFACE")
- rm "$STATE_DIR/profiles/$2"
- set_iface down "$INTERFACE" "$2"
- fi
-}
-
-# set_iface up/down interface [profile]
-# Set interface status to up/down
-# optionally link it to a profile.
-#
-set_iface() {
- local PROFILE="${3:-external}"
- if [[ "$1" == "up" ]]; then
- echo "$PROFILE" > "$STATE_DIR/interfaces/$2"
- elif [[ "$1" == "down" ]]; then
- rm -f "$STATE_DIR/interfaces/$2" # JP: add -f so we don't complain if the interface isn't up
- fi
-}
-
-is_interface() {
- local INTERFACE="$1"
- if [[ ! -e "/sys/class/net/$INTERFACE" ]]; then
- if ! echo "$INTERFACE" | grep -F -q ":"; then
- return 1
- fi
- fi
- return 0
-}
-
-interface_is_up() {
- local flags
- read flags < "/sys/class/net/$1/flags"
- # IFF_UP is defined as 0x1 in linux/if.h
- (( flags & 0x1 ))
-}
-
-## Changes a network interface state.
-# $1: up, flush, or down.
-# $2: the interface name
-bring_interface()
-{
- local INTERFACE="$2"
- case "$1" in
- up)
- ip link set dev "$INTERFACE" up &>/dev/null
- timeout_wait "${UP_TIMEOUT:-5}" 'interface_is_up "$INTERFACE"' || return 1
- ;;
- flush|down)
- ip addr flush dev "$INTERFACE" &>/dev/null
- ;;&
- down)
- ip link set dev "$INTERFACE" down &>/dev/null
- ;;
- esac
-}
# vim: ft=sh ts=4 et sw=4: