119 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
| #!/bin/sh
 | |
| # Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
 | |
| #
 | |
| # Permission to use, copy, modify, and/or distribute this software for any
 | |
| # purpose with or without fee is hereby granted, provided that the above
 | |
| # copyright notice and this permission notice appear in all copies.
 | |
| #
 | |
| # This software is provided 'as is' and without any warranty, express or
 | |
| # implied.  In no event shall the authors be liable for any damages arising
 | |
| # from the use of this software.
 | |
| #
 | |
| # Manage wifi connections using wpa_supplicant.
 | |
| #
 | |
| # Vocabulary:
 | |
| #   wifi-ssid - The SSID name to connect to.
 | |
| #   wifi-psk - The pre-shared key to use.
 | |
| #   wifi-config - A path to a wpa_supplicant config file, for special configs.
 | |
| #
 | |
| # If wifi-config is not set, wifi-ssid and wifi-psk are required, and a config
 | |
| # will be generated as /run/wpa_supplicant.$IFACE.conf.
 | |
| #
 | |
| # The wpa_supplicant PID is stored in /run/wpa_supplicant.$IFACE.pid.
 | |
| 
 | |
| die() {
 | |
| 	printf "ERROR: %s\n" "$1" >&2
 | |
| 	exit 1
 | |
| }
 | |
| 
 | |
| [ -z "$IFACE" ] && die "IFACE not set"
 | |
| [ -z "$PHASE" ] && die "PHASE not set"
 | |
| PIDFILE="/run/wpa_supplicant.$IFACE.pid"
 | |
| 
 | |
| # Do not allow mixing wifi-config-path and wifi-ssid/wifi-psk.
 | |
| [ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_SSID" ] && die "wifi-config-path cannot be used with wifi-ssid"
 | |
| [ -n "$IF_WIFI_CONFIG_PATH" -a -n "$IF_WIFI_PSK" ] && die "wifi-config-path cannot be used with wifi-psk"
 | |
| 
 | |
| # Set IF_WIFI_CONFIG_PATH to the default path if not already set.
 | |
| WIFI_CONFIG_PATH="$IF_WIFI_CONFIG_PATH"
 | |
| [ -z "$WIFI_CONFIG_PATH" ] && WIFI_CONFIG_PATH="/run/wpa_supplicant.$IFACE.conf"
 | |
| 
 | |
| # Supplicant options.
 | |
| WPA_SUPPLICANT_OPTS="-qq -B -i$IFACE -c$WIFI_CONFIG_PATH -P$PIDFILE"
 | |
| 
 | |
| # Given $IF_WIFI_SSID and $IF_WIFI_PSK, generate a config file at $WIFI_CONFIG_PATH.
 | |
| generate_config() {
 | |
| 	[ -z "$IF_WIFI_SSID" ] && die "wifi-ssid not set"
 | |
| 	[ -z "$IF_WIFI_PSK" ] && die "wifi-psk not set"
 | |
| 
 | |
| 	# We use a pipeline here to avoid leaking PSK into the process name.
 | |
| 	(echo $IF_WIFI_PSK | /sbin/wpa_passphrase $IF_WIFI_SSID) >$WIFI_CONFIG_PATH
 | |
| 
 | |
| 	[ ! -e "$WIFI_CONFIG_PATH" ] && die "failed to write temporary config: $WIFI_CONFIG_PATH"
 | |
| }
 | |
| 
 | |
| # Should we use the supplicant?
 | |
| use_supplicant() {
 | |
| 	[ -n "$IF_WIFI_CONFIG_PATH" ] && return 0
 | |
| 	[ -n "$IF_WIFI_PSK" ] && return 0
 | |
| 
 | |
| 	return 1
 | |
| }
 | |
| 
 | |
| # Either start a supplicant process for $IFACE, or use iwconfig to trigger an
 | |
| # association attempt.
 | |
| start() {
 | |
| 	if use_supplicant; then
 | |
| 		# If there is no config file located at $WIFI_CONFIG_PATH, generate one.
 | |
| 		[ ! -e "$WIFI_CONFIG_PATH" ] && generate_config
 | |
| 
 | |
| 		/sbin/wpa_supplicant $WPA_SUPPLICANT_OPTS
 | |
| 	else
 | |
| 		/usr/sbin/iwconfig $IFACE essid -- "$IF_WIFI_SSID" ap any
 | |
| 	fi
 | |
| }
 | |
| 
 | |
| # Stop wpa_supplicant safely
 | |
| stop_wpa_supplicant() {
 | |
| 	# Remove generated config file
 | |
| 	[ -z "$IF_WIFI_CONFIG_PATH" ] && rm -- "$WIFI_CONFIG_PATH"
 | |
| 
 | |
| 	# If there is no PIDFILE, there is nothing we can do
 | |
| 	[ ! -d "$PIDFILE" ] && return
 | |
| 
 | |
| 	pid=$(cat "$PIDFILE")
 | |
| 	rm -- "$PIDFILE"
 | |
| 
 | |
| 	# If there is no process with this PID running, we're done here
 | |
| 	if [ ! -d "/proc/$pid/" ]; then
 | |
| 		return
 | |
| 	fi
 | |
| 
 | |
| 	# Verify that the name of the running process matches wpa_supplicant
 | |
| 	progname_path=$(readlink -n "/proc/$pid/exe")
 | |
| 	progname=$(basename "$progname_path")
 | |
| 	if [ "$progname" = "wpa_supplicant" ]; then
 | |
| 		kill -9 $pid 2>/dev/null
 | |
| 	fi
 | |
| }
 | |
| 
 | |
| # Either stop the supplicant process for $IFACE, or use iwconfig to dissociate
 | |
| # from the current SSID.
 | |
| stop() {
 | |
| 	if use_supplicant; then
 | |
| 		stop_wpa_supplicant
 | |
| 	else
 | |
| 		/usr/sbin/iwconfig $IFACE essid any
 | |
| 	fi
 | |
| }
 | |
| 
 | |
| [ -z "$VERBOSE" ] || set -x
 | |
| 
 | |
| case "$PHASE" in
 | |
| pre-up)
 | |
| 	start
 | |
| 	;;
 | |
| post-down)
 | |
| 	stop
 | |
| 	;;
 | |
| esac
 |