diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/connections/openvpn | 52 | ||||
-rw-r--r-- | src/connections/ppp | 31 | ||||
-rwxr-xr-x | src/hooks/fancy | 90 | ||||
-rwxr-xr-x | src/hooks/initscripts | 35 | ||||
-rwxr-xr-x | src/ifplugd.action | 49 | ||||
-rw-r--r-- | src/lib/8021x (renamed from src/8021x) | 0 | ||||
-rwxr-xr-x | src/lib/auto.action | 56 | ||||
-rw-r--r-- | src/lib/connections/README | 28 | ||||
-rw-r--r-- | src/lib/connections/bond (renamed from src/connections/bond) | 0 | ||||
-rw-r--r-- | src/lib/connections/bridge (renamed from src/connections/bridge) | 0 | ||||
-rw-r--r-- | src/lib/connections/ethernet (renamed from src/connections/ethernet) | 0 | ||||
-rw-r--r-- | src/lib/connections/pppoe (renamed from src/connections/pppoe) | 0 | ||||
-rw-r--r-- | src/lib/connections/tunnel (renamed from src/connections/tunnel) | 0 | ||||
-rw-r--r-- | src/lib/connections/tuntap (renamed from src/connections/tuntap) | 0 | ||||
-rw-r--r-- | src/lib/connections/vlan (renamed from src/connections/vlan) | 0 | ||||
-rw-r--r-- | src/lib/connections/wireless (renamed from src/connections/wireless) | 0 | ||||
-rw-r--r-- | src/lib/globals (renamed from src/globals) | 0 | ||||
-rw-r--r-- | src/lib/network (renamed from src/network) | 0 | ||||
-rw-r--r-- | src/lib/rfkill (renamed from src/rfkill) | 0 | ||||
-rwxr-xr-x | src/netctl | 106 | ||||
-rwxr-xr-x | src/netctl-auto | 87 | ||||
-rwxr-xr-x | src/wifi-menu | 263 |
22 files changed, 589 insertions, 208 deletions
diff --git a/src/connections/openvpn b/src/connections/openvpn deleted file mode 100644 index 170d582..0000000 --- a/src/connections/openvpn +++ /dev/null @@ -1,52 +0,0 @@ -#! /bin/bash -# Originally contributed by Thomas Jost: https://bugs.archlinux.org/task/21490 - -. /usr/lib/network/network - -openvpn_up() { - load_profile "$1" - [[ -z "$OVPN_CONFIG" ]] && OVPN_CONFIG="/etc/openvpn/openvpn.conf" - [[ -z "$OVPN_PID_FILE" ]] && OVPN_PID_FILE="/run/openvpn-$1.pid" - [[ -z "$OVPN_FLAGS" ]] && OVPN_FLAGS="" - - OVPN_CONF_DIR="`dirname $OVPN_CONFIG`" - OVPN_CONF_FILE="`basename $OVPN_CONFIG`" - - /usr/sbin/openvpn --writepid $OVPN_PID_FILE --daemon --cd "$OVPN_CONF_DIR" --config "$OVPN_CONF_FILE" $OVPN_FLAGS - - if [[ $? -ne 0 ]]; then - report_fail "OpenVPN connection failed" - exit 1 - fi - - # Generate a new resolv.conf - if [[ -n "$DNS" ]]; then - [[ -e /etc/resolv.conf ]] && cp /etc/resolv.conf /tmp/openvpn-$1-resolv.conf - : >/etc/resolv.conf - [[ -n "$DOMAIN" ]] && echo "domain $DOMAIN" >>/etc/resolv.conf - [[ -n "$SEARCH" ]] && echo "search $SEARCH" >>/etc/resolv.conf - for dns in "${DNS[@]}"; do - echo "nameserver $dns" >>/etc/resolv.conf - done - for dnsoption in "${DNS_OPTIONS[@]}"; do - echo "options $dnsoption" >>/etc/resolv.conf - done - fi -} - -openvpn_down() { - load_profile "$1" - [[ -z "$OVPN_PID_FILE" ]] && OVPN_PID_FILE="/run/openvpn-$1.pid" - - kill $(head -1 $OVPN_PID_FILE) - rm $OVPN_PID_FILE - - # Restore an old resolv.conf - if [[ -e /tmp/openvpn-$1-resolv.conf ]]; then - mv -f /tmp/openvpn-$1-resolv.conf /etc/resolv.conf - fi -} - -openvpn_$1 "$2" -exit $? -# vim: ft=sh ts=4 et sw=4: diff --git a/src/connections/ppp b/src/connections/ppp deleted file mode 100644 index da0fd6f..0000000 --- a/src/connections/ppp +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/bash -. /usr/lib/network/network - - -ppp_up() { - 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 - report_fail "Couldn't make pppd connection." - return 1 - fi -} - -ppp_down() { - load_profile "$1" - PIDFILE="/var/run/ppp-$(basename $PEER).pid" - - if [[ -e $PIDFILE ]]; then - PID=$(head -1 $PIDFILE) - [[ -n "$PID" ]] && kill "$PID" - fi -} - -ppp_$1 "$2" -exit $? - -# vim: ft=sh ts=4 et sw=4: diff --git a/src/hooks/fancy b/src/hooks/fancy deleted file mode 100755 index a64514e..0000000 --- a/src/hooks/fancy +++ /dev/null @@ -1,90 +0,0 @@ -# Fancy output is for terminal output only. -[[ -t 1 ]] || return - - -### Fancy Logging/Error reporting - -function report_err { - print_prefixed "${FANCY_OTHER}" "${FANCY_HIGHLIGHT}$*" -} - -function report_notice { - print_prefixed "${FANCY_OTHER}" "$*" -} - -function report_try { - printf "${FANCY_OTHER}${PREFIX_BUSY}${FANCY_NORMAL} %s " "$*" - report_busy - REPORT_TRYING=1 -} - -function report_fail { - if [[ -n "$*" ]]; then - if [[ -n "$REPORT_TRYING" ]]; then - report_append "$*" - report_failed - REPORT_TRYING= - else - print_prefixed "${FANCY_FAILED}" "${FANCY_HIGHLIGHT}$*" - fi - elif [[ -n "$REPORT_TRYING" ]]; then - report_failed - REPORT_TRYING= - fi -} - -function report_success { - if [[ -n "$*" ]]; then - if [[ -n "$REPORT_TRYING" ]]; then - report_append "$*" - report_done - REPORT_TRYING= - else - print_prefixed "${FANCY_DONE}" "$*" - fi - elif [[ -n "$REPORT_TRYING" ]]; then - report_done - REPORT_TRYING= - fi -} - -function report_append { - printf -- "${RESTORE_POSITION}${FANCY_OTHER}-${FANCY_NORMAL} %s " "$*" -} - -function report_busy { - printf "${CURSOR_STATUS} [${FANCY_BUSY} BUSY ${FANCY_NORMAL}] " -} - -function report_failed { - printf "${CURSOR_STATUS} [${FANCY_FAILED}FAILED${FANCY_NORMAL}]\n" -} - -function report_done { - printf "${CURSOR_STATUS} [${FANCY_DONE} DONE ${FANCY_NORMAL}]\n" -} - -function print_prefixed { - local c_prefix=$1 - shift - printf "${c_prefix}${PREFIX_ATTENTION}${FANCY_NORMAL} %s${FANCY_NORMAL}\n" "$*" -} - - -SAVE_POSITION=$(tput sc) -RESTORE_POSITION=$(tput rc) -COLUMNS=$(tput cols) -(( COLUMNS == 0 )) && COLUMNS=80 -CURSOR_STATUS=${SAVE_POSITION}$(tput hpa $(( COLUMNS - 10 )) ) - -FANCY_NORMAL=$(tput sgr0) -FANCY_HIGHLIGHT=${FANCY_NORMAL}$(tput bold) -FANCY_BUSY=${FANCY_NORMAL}$(tput setaf 6) # cyan -FANCY_FAILED=${FANCY_HIGHLIGHT}$(tput setaf 1) # red -FANCY_DONE=${FANCY_HIGHLIGHT}$(tput setaf 2) # green -FANCY_OTHER=${FANCY_HIGHLIGHT}$(tput setaf 4) # blue - -PREFIX_BUSY="::" -PREFIX_ATTENTION=" >" - -# vim: ft=sh ts=4 et sw=4: diff --git a/src/hooks/initscripts b/src/hooks/initscripts deleted file mode 100755 index 07003c8..0000000 --- a/src/hooks/initscripts +++ /dev/null @@ -1,35 +0,0 @@ -# Use initscripts output formatting. -# This hook must be loaded after 'fancy'. - -[[ ${FANCY_NORMAL+x} = x && -f /etc/rc.d/functions ]] || return -. /etc/rc.conf -. /etc/rc.d/functions - - -function report_try { - stat_busy "$*" - REPORT_TRYING=1 -} - -function report_append { - stat_append "- $*" -} - -function report_failed { - stat_fail -} - -function report_done { - stat_done -} - - -FANCY_NORMAL=$C_CLEAR -FANCY_HIGHLIGHT=$C_H1 -FANCY_FAILED=$C_FAIL -FANCY_DONE=$C_DONE -FANCY_OTHER=$C_OTHER - -PREFIX_ATTENTION=$PREFIX_HL - -# vim: ft=sh ts=4 et sw=4: diff --git a/src/ifplugd.action b/src/ifplugd.action new file mode 100755 index 0000000..ea3a16c --- /dev/null +++ b/src/ifplugd.action @@ -0,0 +1,49 @@ +#!/bin/bash +# +# ifplugd.action script for netcfg + +. /usr/lib/network/network + +case "$2" in + up) + # Look for a dhcp based profile to try first + # dhcp can actually outright fail, whereas + # it's difficult to tell if static succeeded + # Also check profile is same iface and is right connection + echo "up" + declare -a preferred_profiles + declare -a dhcp_profiles + declare -a static_profiles + for profile in $(list_profiles); do + ( + echo "loading $profile" + load_profile "$profile" + [[ "$INTERFACE" == "$1" && "$CONNECTION" == "ethernet" ]] || continue + checkyesno "${AUTO_WIRED:-no}" && exit 1 # user preferred AUTO profile + [[ "$IP" == "dhcp" ]] && exit 2 # dhcp profile + exit 3 # static profile + ) + case $? in + 1) preferred_profiles+=("$profile");; + 2) dhcp_profiles+=("$profile");; + 3) static_profiles+=("$profile");; + esac + done + if [[ ${#preferred_profiles[@]} > 1 ]]; then + echo "AUTO_WIRED flag for $1 set in more than one profile (${preferred_profiles[*]})" + fi + for profile in "${preferred_profiles[@]}" "${dhcp_profiles[@]}" "${static_profiles[@]}"; do + profile_up "$profile" && exit 0 + done + ;; + down) + if check_iface "$1"; then + interface_down "$1" && exit 0 + fi + ;; + *) + echo "Wrong arguments" > /dev/stderr + ;; +esac + +exit 1 diff --git a/src/8021x b/src/lib/8021x index d2ddfe4..d2ddfe4 100644 --- a/src/8021x +++ b/src/lib/8021x diff --git a/src/lib/auto.action b/src/lib/auto.action new file mode 100755 index 0000000..1f29364 --- /dev/null +++ b/src/lib/auto.action @@ -0,0 +1,56 @@ +#! /bin/bash + +interface="$1" +ssid="$2" +profile="$3" +action="$4" + +. /usr/lib/network/network +[[ "$profile" ]] && load_profile "$profile" + +case $action in + CONNECT) + if [[ -z $profile ]]; then + # Load interface specific config + [[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface" + dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" -K $DHCP_OPTIONS "$interface" + exit $? + fi + if ! DHCPCD_INTERNAL_OPTIONS="-K" $CONN_DIR/ethernet up "$profile"; then + exit 1 # what to do if fail? + fi + + set_profile up "$profile" + + if ! ( eval $POST_UP ); then # JP: sandbox the eval + # failing POST_UP will take interface down + "$CONN_DIR/$ethernet" down "$profile" + exit 1 + fi + ;; + DISCONNECT) + if [[ -z $profile ]]; then + dhcpcd -k "$interface" + exit $? + fi + if ! ( eval $PRE_DOWN ); then # JP: sandbox the eval + exit 1 + fi + if ! "$CONN_DIR/ethernet" down "$profile"; then + exit 1 + fi + if ! ( eval $POST_DOWN ); then # JP: sandbox the eval + exit 1 + fi + set_profile down "$profile" + ;; + LOST|REESTABLISHED) + # Not handled. + exit 0 + ;; + *) + # ??? + exit 1 + ;; +esac + diff --git a/src/lib/connections/README b/src/lib/connections/README new file mode 100644 index 0000000..38ef11a --- /dev/null +++ b/src/lib/connections/README @@ -0,0 +1,28 @@ +Support for connection types is implemented by connection files in + + /usr/lib/network/connections/ + +The file name determines the name of the connection type, so support +for the aviancarrier connection type will be provided by the file: + + /usr/lib/network/connections/aviancarrier + +Files that implement support for a connection type should NOT be +executable. Such files should contain valid Bash code, among which two +functions, namely <connection_type>_up and <connection_type>_down. For +the aviancarrier file this would be: + + aviancarrier_up + aviancarrier_down + +These functions are responsible for bringing the network up and down, +respectively. When the functions are called, three bash files are +already sourced, so all functions and variables in those files are +available. The readily sourced files are: + + /usr/lib/network/network + /usr/lib/network/globals + /etc/network.d/<profile> + +Here, <profile> is the profile file specifying the desired network +configuration. diff --git a/src/connections/bond b/src/lib/connections/bond index bc5aa95..bc5aa95 100644 --- a/src/connections/bond +++ b/src/lib/connections/bond diff --git a/src/connections/bridge b/src/lib/connections/bridge index 6b3ab67..6b3ab67 100644 --- a/src/connections/bridge +++ b/src/lib/connections/bridge diff --git a/src/connections/ethernet b/src/lib/connections/ethernet index 487adf8..487adf8 100644 --- a/src/connections/ethernet +++ b/src/lib/connections/ethernet diff --git a/src/connections/pppoe b/src/lib/connections/pppoe index 17fe42d..17fe42d 100644 --- a/src/connections/pppoe +++ b/src/lib/connections/pppoe diff --git a/src/connections/tunnel b/src/lib/connections/tunnel index 6cefc5c..6cefc5c 100644 --- a/src/connections/tunnel +++ b/src/lib/connections/tunnel diff --git a/src/connections/tuntap b/src/lib/connections/tuntap index 6985c8c..6985c8c 100644 --- a/src/connections/tuntap +++ b/src/lib/connections/tuntap diff --git a/src/connections/vlan b/src/lib/connections/vlan index 75c7fa9..75c7fa9 100644 --- a/src/connections/vlan +++ b/src/lib/connections/vlan diff --git a/src/connections/wireless b/src/lib/connections/wireless index 135bec7..135bec7 100644 --- a/src/connections/wireless +++ b/src/lib/connections/wireless diff --git a/src/globals b/src/lib/globals index 491f9d6..491f9d6 100644 --- a/src/globals +++ b/src/lib/globals diff --git a/src/network b/src/lib/network index 1aa384c..1aa384c 100644 --- a/src/network +++ b/src/lib/network diff --git a/src/rfkill b/src/lib/rfkill index 1832dc1..1832dc1 100644 --- a/src/rfkill +++ b/src/lib/rfkill diff --git a/src/netctl b/src/netctl new file mode 100755 index 0000000..f1d79e8 --- /dev/null +++ b/src/netctl @@ -0,0 +1,106 @@ +#!/bin/bash + +. /usr/lib/network/network + +NETCFG_VER=2-notpackaged + +version() +{ + echo "netcfg v$NETCFG_VER" +} + +usage() +{ + version + cat << END +Usage: + Start specified profile: netcfg profile + Other functions: netcfg argument profile +Arguments: + current Report currently running profiles +-a, all-down Take all active profiles down +-c, check-iface Do not start profile if interface is already up +-d, down Take specified profile down +-D, iface-down Take down profile active on specified interface +-h, help This help message +-l, list List all available profiles +-r, reconnect Disconnect and reconnect specified profile +-R, iface-recon Reconnect profile active on specified interface +-u, up Start specified profile +-v, version Output version information and exit + all-resume Resume previously suspended profiles and reconnect them + all-suspend Store a list of current running profiles and suspend them +END +} + +# TODO: Re-add ROOT check and rewrite with getopts from BashFAQ + +case "$1" in + --version|-v|version) + version + exit 0;; + --help|-h|help) + usage + exit 0;; + list|-l) + list_profiles + exit 0;; + current|-s|status) + if [[ -d "$STATE_DIR/profiles/" ]]; then + ls "$STATE_DIR/profiles/" + exit 0 + else + exit_stderr "No active profiles." + fi;; +esac + +if [[ $(id -u) -gt 0 ]]; then + exit_stderr "This script should be run as root." +fi + +# Ensure cwd is not in a transient directory, which may prevent unmounting due to netcfg children +cd / + +case "$1" in + -c|check-iface|-u|up) + CHECK="YES" + profile_up "$2";; + -d|down) + profile_down "$2";; + -D|iface-down) + interface_down "$2";; + -a|all-down) + all_down;; + -r|reconnect) + profile_down "$2" + profile_up "$2";; + -R|iface-recon) + interface_reconnect "$2";; + all-resume) + all_resume;; + all-suspend) + all_suspend;; + clean) + rm "$STATE_DIR/interfaces"/* 2> /dev/null + rm "$STATE_DIR/profiles"/* 2> /dev/null + rm "$STATE_DIR/suspend"/* 2> /dev/null + rm "$STATE_DIR/netcfg-daemon" 2> /dev/null + killall wpa_supplicant 2> /dev/null + killall dhcpcd 2> /dev/null + killall dhclient 2> /dev/null + ;; + -*|--*) + usage + exit 1;; + *) + if [[ -n "$1" ]]; then + profile_up "$1" + else + usage + exit 1 + fi + ;; +esac +exit $? + +# vim: ft=sh ts=4 et sw=4: diff --git a/src/netctl-auto b/src/netctl-auto new file mode 100755 index 0000000..c6aaf67 --- /dev/null +++ b/src/netctl-auto @@ -0,0 +1,87 @@ +#! /bin/bash +. /usr/lib/network/network +. "$SUBR_DIR/8021x" +. "$SUBR_DIR/rfkill" +. /etc/conf.d/netcfg + +AUTOWIFI="/usr/sbin/wpa_actiond -p /run/wpa_supplicant" +ACTION_SCRIPT="/usr/bin/netcfg-wpa_actiond-action" + +case $1 in + help) + echo "netcfg-wpa_actiond <interface>" + echo "netcfg-wpa_actiond stop <interface>" + exit + ;; + stop) + [[ -z $2 ]] && echo "Please specify an interface to stop" && exit 1 + interface=$2 + PIDFILE="/run/wpa_actiond_${interface}.pid" + [[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface" + netcfg -D "$interface" + timeout_wait 1 '[[ ! -f "$PIDFILE" ]]' || kill "$(< "$PIDFILE")" + # only try to disable software rfkill switches (FS#25514) + if [[ "$RFKILL" == "soft" ]]; then + set_rf_state "$interface" disabled $RFKILL_NAME || exit $? + fi + exit + ;; + *) + interface=$1; shift + PIDFILE="/run/wpa_actiond_${interface}.pid" + EXTRA_AUTOWIFI_OPTIONS="$*" + ;; +esac + +if [[ -z $interface ]]; then + echo "No interface specified" + exit 1 +fi + +# Load interface specific config +[[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface" + +if [[ -f "$CONN_DIR/interfaces/$interface" ]]; then + netcfg -D "$interface" +fi + +if [[ -n "$RFKILL" ]]; then # Enable radio if necessary + enable_rf "$interface" "$RFKILL" "$RFKILL_NAME" || exit $? +fi + +WPA_CONF="$(make_wpa_config_file "$interface")" + +if [[ -n "${AUTO_PROFILES}" ]]; then + for prof in "${AUTO_PROFILES[@]}"; do echo "$prof"; done +else + list_profiles +fi | while read profile; do + echo "$profile" + ( + load_profile "$profile" + + [[ $CONNECTION != "wireless" ]] && exit 1 + [[ $INTERFACE != $interface ]] && exit 1 + # Exclude wpa-config, the wpa_conf is 'complete' and doesn't fit in this scheme + [[ -z "$SECURITY" ]] && SECURITY="none" + [[ $SECURITY == "wpa-config" ]] && exit 1 + + printf "%s\n" "network={" "$(make_wpa_config)" "id_str=\"$profile\"" "}" >> "$WPA_CONF" + ) +done + + +[[ -z $WPA_DRIVER ]] && WPA_DRIVER="nl80211,wext" +WPA_OPTS="-W $WPA_OPTS" + +# Kill any existing wpa_supplicant on this interface +stop_wpa "$interface" &> /dev/null + +if start_wpa "$interface" "$WPA_CONF" "$WPA_DRIVER" $WPA_OPTS; then + if $AUTOWIFI -i "$interface" -P "$PIDFILE" -a "$ACTION_SCRIPT" $EXTRA_AUTOWIFI_OPTIONS; then + exit 0 + fi +fi + +exit 1 + diff --git a/src/wifi-menu b/src/wifi-menu new file mode 100755 index 0000000..f46db0d --- /dev/null +++ b/src/wifi-menu @@ -0,0 +1,263 @@ +#! /bin/bash + +. /usr/lib/network/network +. "$SUBR_DIR/8021x" +. /etc/conf.d/netcfg + +usage() +{ + cat << END +Usage: wifi-menu [-o | --obscure] [-h | --help] [interface] + +Interactively connect to a wireless network. + +Arguments: + -o, --obscure Show asterisks for the characters of the password + and store the password as a hexadecimal string. + -h, --help Show this help. + interface The wireless interface to use. + (default: WIRELESS_INTERFACE from /etc/conf.d/netcfg) + +For choosing from all available profiles, use netcfg-menu. +END +} + +# Fills PROFILES and ESSIDS with the profile names and essids of the profiles +# for interface $1. +init_profiles() +{ + local i=0 essid profile + while read profile; do + essid=$( + unset INTERFACE ESSID + . "$PROFILE_DIR/$profile" &> /dev/null + if [[ "$INTERFACE" = "$1" && -n "$ESSID" ]]; then + printf "%s" "$ESSID" + if [[ "$DESCRIPTION" =~ "Automatically generated" ]]; then + return 2 + else + return 1 + fi + fi + return 0 + ) + case $? in + 2) + GENERATED+=("$profile") + ;& + 1) + PROFILES[i]=$profile + ESSIDS[i]=$essid + (( ++i )) + ;; + esac + done < <(list_profiles) +} + +# Builds ENTRIES as an argument list for dialog based on scan results in $1. +init_entries() +{ + local i=0 flags signal ssid + while IFS=$'\t' read signal flags ssid; do + ENTRIES[i++]="--" # $ssid might look like an option to dialog. + ENTRIES[i++]=$ssid + if inarray "$ssid" "${ESSIDS[@]}"; then + if inarray "$(ssid_to_profile "$ssid")" "${GENERATED[@]}"; then + ENTRIES[i]="+" # Automatically generated + else + ENTRIES[i]="*" # Handmade + fi + else + ENTRIES[i]="-" # Not present + fi + if [[ "$ssid" = "$CONNECTION" ]]; then + ENTRIES[i]="!" # Currently connected + fi + if [[ "$flags" =~ WPA2|WPA|WEP ]]; then + ENTRIES[i]+=":${BASH_REMATCH[0],,}" + else + ENTRIES[i]+=":none" + fi + ENTRIES[i]+=" :$signal" + (( ++i )) + done < "$1" +} + +# Finds a profile name for ssid $1. +ssid_to_profile() +{ + local i + for i in $(seq 0 $((${#ESSIDS[@]}-1))); do + if [[ "$1" = "${ESSIDS[i]}" ]]; then + printf "%s" "${PROFILES[i]}" + return 0 + fi + done + return 1 +} + +# Creates a profile for ssid $1. +create_profile() +{ + local box flags key msg security + PROFILE="$INTERFACE-${1//\//_}" + [[ -e "$PROFILE_DIR/$PROFILE" ]] && PROFILE+=".wifi-menu" + flags=$(grep -m 1 $'\t'"$1\$" "$NETWORKS" | cut -f 2) + if [[ "$flags" =~ WPA|WEP ]]; then + security=${BASH_REMATCH[0],,} + else + security=none + fi + if [[ "$flags" =~ PSK|WEP ]]; then + [[ "$OBSCURE" ]] && box="--insecure --passwordbox" || box="--inputbox" + msg="Enter $security security key for\n'$1'" + key=$(dialog $box "$msg" 10 40 --stdout) || return $? + if [[ "${#key}" -ge 8 && "${#key}" -le 63 ]]; then + if [[ "$OBSCURE" ]]; then + key=$(wpa_passphrase "$1" "$key" | grep -m 1 "^[[:space:]]*psk=") + key=${key#*psk=} + else + key=$(printf "%q" "$key") + fi + elif ! [[ "${#key}" -eq 64 && "$key" = +([[:xdigit:]]) ]]; then + return 4 + fi + fi + cat << EOF > "$PROFILE_DIR/$PROFILE" +CONNECTION='wireless' +DESCRIPTION='Automatically generated profile by wifi-menu' +INTERFACE='$INTERFACE' +SECURITY='$security' +ESSID=$(printf "%q" "$1") +IP='dhcp' +${key+KEY=$key} +EOF + printf "%s" "$PROFILE" + return 0 +} + +# Connects to ssid $1 using an available profile or an automatically created +# one if none exists. +connect_to_ssid() +{ + local msg + PROFILE=$(ssid_to_profile "$1") + if [[ $? -eq 0 ]]; then + clear + check_profile "$PROFILE" && profile_down "$PROFILE" + else + PROFILE=$(create_profile "$1") + RETURN=$? + (( RETURN == 0 )) || return $RETURN + SPAWNED_PROFILE=1 + clear + fi + if ! profile_up "$PROFILE"; then + if (( SPAWNED_PROFILE )); then + msg=" CONNECTING FAILED + +Do you want to keep the generated profile ('$PROFILE')?" + dialog --yesno "$msg" 10 40 --stdout || rm "$PROFILE_DIR/$PROFILE" + clear + fi + return 2 + fi + return 0 +} + +while [[ "$1" = -* ]]; do + case "$1" in + -h|--help) + usage + exit + ;; + -o|--obscure) + OBSCURE=1 + shift + ;; + -*) + report_err "Invalid option: $1" + usage + exit 255 + ;; + esac +done +if [[ $# -gt 1 ]]; then + report_err "Too many arguments" + usage + exit 255 +fi + +if [[ $(id -u) -ne 0 ]]; then + exit_stderr "This script needs to be run with root privileges" +fi +if ! type dialog &> /dev/null; then + exit_stderr "Please install 'dialog' to use wifi-menu" +fi + +INTERFACE=${1-$WIRELESS_INTERFACE} +if [[ -z "$INTERFACE" ]]; then + report_err "Missing interface specification" + usage + exit 255 +fi + +cd / # We do not want to spawn anything that can block unmounting +is_interface "$INTERFACE" || exit_fail "No such interface: $INTERFACE" +if ! interface_is_up "$INTERFACE"; then + [[ -f "$IFACE_DIR/$INTERFACE" ]] && . "$IFACE_DIR/$INTERFACE" + bring_interface up "$INTERFACE" || exit_fail "Interface unavailable" + SPAWNED_INTERFACE=1 +fi + +report_try "Scanning for networks" +CONNECTION=$(wpa_call "$INTERFACE" status 2> /dev/null | grep -m 1 "^ssid=") +CONNECTION=${CONNECTION#ssid=} +NETWORKS=$(wpa_supplicant_scan "$INTERFACE" 3,4,5) +if [[ $? -eq 0 ]]; then + trap 'rm -f "$NETWORKS"' EXIT + report_success + init_profiles "$INTERFACE" + init_entries "$NETWORKS" + MSG="Select the network you wish to use +Flags description: + * - handmade profile present + + - automatically generated profile present + - - no profile present + ! - active connection present" + CHOICE=$(dialog --column-separator : --menu "$MSG" 24 50 12 \ + "${ENTRIES[@]}" --stdout) + RETURN=$? + if (( RETURN == 0 )); then + connect_to_ssid "$CHOICE" + RETURN=$? + fi +else + report_fail + RETURN=3 +fi + +case $RETURN in + 0|2) # Connected | Connecting failed + ;; + 1) # Canceled + clear + ;; + 3) # No networks found + report_err "No networks found" + ;; + 4) # Invalid passphrase length (WEP keys have tighter restrictions) + clear + report_err "Passphrase must be 8..63 characters" + ;; + 255) # ESC or error + clear + report_err "Aborted" + ;; + *) # Should not happen + report_err "Unexpected return code from dialog: $RETURN" + RETURN=7 + ;; +esac +(( RETURN && SPAWNED_INTERFACE )) && bring_interface down "$INTERFACE" +exit $RETURN |