From 47feaba1b2c8891d57dd58b3420c6517e08e474b Mon Sep 17 00:00:00 2001 From: Jonatan Schlag Date: Fri, 18 Aug 2017 13:45:19 +0200 Subject: [PATCH] wireless: add network feature See http://wiki.ipfire.org/devel/network/wireless-networks Signed-off-by: Jonatan Schlag Signed-off-by: Michael Tremer --- src/functions/functions.constants | 2 + src/functions/functions.wireless | 317 ++++++++++++++++++++++++++++++ src/network | 2 +- 3 files changed, 320 insertions(+), 1 deletion(-) diff --git a/src/functions/functions.constants b/src/functions/functions.constants index 78801da0..1fad6288 100644 --- a/src/functions/functions.constants +++ b/src/functions/functions.constants @@ -51,6 +51,8 @@ WPA_SUPPLICANT_CONF_DIR="/etc/wpa_supplicant" # Network file configuration. NETWORK_SETTINGS_FILE=${NETWORK_CONFIG_DIR}/config NETWORK_SETTINGS_FILE_PARAMS="DEBUG" +NETWORK_WIRELESS_NETWORK_DIR="${NETWORK_CONFIG_DIR}/wireless/networks" + CONFIG_HOSTNAME="/etc/hostname" RED_DB_DIR=${RUN_DIR}/red diff --git a/src/functions/functions.wireless b/src/functions/functions.wireless index 57377e1a..0471d9e6 100644 --- a/src/functions/functions.wireless +++ b/src/functions/functions.wireless @@ -25,6 +25,14 @@ NETWORK_SETTINGS_FILE_PARAMS="${NETWORK_SETTINGS_FILE_PARAMS} WIRELESS_REGULATOR WIRELESS_REGULATORY_DOMAIN_DATABASE="/usr/lib/crda/regulatory.bin" +WIRELESS_NETWORK_CONFIG_SETTINGS="\ + SSID \ + ENCRYPTION_MODE \ + KEY \ + PRIORITY" + +WIRELESS_NETWORKS_VALID_ENCRYPTION_MODES="WPA2-PSK" + wireless_create() { local device=${1} assert isset device @@ -399,3 +407,312 @@ wireless_monitor() { return ${EXIT_OK} } + +cli_wireless() { + local action=${1} + shift 1 + + case "${action}" in + network) + cli_wireless_network "$@" + ;; + *) + error "Unrecognized argument: ${action}" + exit ${EXIT_ERROR} + ;; + esac +} + +cli_wireless_network() { + if wireless_network_exists "${1}"; then + local ssid="${1}" + local key="${2}" + key=${key//-/_} + shift 2 + + case "${key}" in + encryption_mode|key|priority) + wireless_network_${key} "${ssid}" "$@" + ;; + show) + wireless_network_show "${ssid}" + exit $? + ;; + *) + error "Unrecognized argument: ${key}" + exit ${EXIT_ERROR} + ;; + esac + else + local action=${1} + shift + + case "${action}" in + new) + wireless_network_new "$@" + ;; + destroy) + wireless_network_destroy "$@" + ;; + ""|*) + if [ -n "${action}" ]; then + error "Unrecognized argument: '${action}'" + fi + exit ${EXIT_ERROR} + ;; + esac + fi +} + +# This function writes all values to a via ${ssid} specificated wireless network configuration file +wireless_network_write_config() { + assert [ $# -ge 1 ] + + local ssid="${1}" + + local ssid_hash="$(wireless_network_hash "${ssid}")" + assert isset ssid_hash + + if ! wireless_network_exists "${ssid}"; then + log ERROR "No such wireless network: '${ssid}'" + return ${EXIT_ERROR} + fi + + local path="${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}/settings" + + if ! settings_write "${path}" ${WIRELESS_NETWORK_CONFIG_SETTINGS}; then + log ERROR "Could not write configuration settings for wireless network ${ssid}" + return ${EXIT_ERROR} + fi + + # When we get here the writing of the config file was successful + return ${EXIT_OK} +} + +# This funtion writes the value for one key to a via ${ssid} specificated +# wireless network configuration file +wireless_network_write_config_key() { + assert [ $# -ge 3 ] + + local ssid="${1}" + local key="${2}" + shift 2 + + local value="$@" + + if ! wireless_network_exists "${ssid}"; then + log ERROR "No such wireless network: ${ssid}" + return ${EXIT_ERROR} + fi + + log DEBUG "Set '${key}' to new value '${value}' in wireless network '${ssid}'" + + local ${WIRELESS_NETWORK_CONFIG_SETTINGS} + + # Read the config settings + if ! wireless_network_read_config "${ssid}"; then + return ${EXIT_ERROR} + fi + + # Set the key to a new value + assign "${key}" "${value}" + + if ! wireless_network_write_config "${ssid}"; then + return ${EXIT_ERROR} + fi + + return ${EXIT_OK} +} + +# Reads one or more keys out of a settings file or all if no key is provided. +wireless_network_read_config() { + assert [ $# -ge 1 ] + + local ssid="${1}" + shift 1 + + local ssid_hash="$(wireless_network_hash "${ssid}")" + assert isset ssid_hash + + if ! wireless_network_exists "${ssid}"; then + log ERROR "No such wireless network : ${ssid}" + return ${EXIT_ERROR} + fi + + local args + if [ $# -eq 0 ] && [ -n "${WIRELESS_NETWORK_CONFIG_SETTINGS}" ]; then + list_append args ${WIRELESS_NETWORK_CONFIG_SETTINGS} + else + list_append args "$@" + fi + + local path="${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}/settings" + + if ! settings_read "${path}" ${args}; then + log ERROR "Could not read settings for wireless network ${ssid}" + return ${EXIT_ERROR} + fi +} + +# This function checks if a wireless network exists +# Returns True when yes and false when not +wireless_network_exists() { + assert [ $# -eq 1 ] + + local ssid="${1}" + local ssid_hash="$(wireless_network_hash "${ssid}")" + assert isset ssid_hash + + local path="${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}" + + # We cannot use wireless_network_read_config here beacuse we would end in a loop + local SSID + + local path_settings="${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}/settings" + + if ! settings_read "${path_settings}" SSID; then + return ${EXIT_FALSE} + fi + + assert isset SSID + + if [ -d "${path}" ] && [[ "${ssid}" = "${SSID}" ]]; then + return ${EXIT_TRUE} + else + return ${EXIT_FALSE} + fi +} + +wireless_network_hash() { + assert [ $# -eq 1 ] + + local string="${1}" + + local hash=$(echo -n "${string}" | md5sum ) + hash=${hash%% -} + + local path="${NETWORK_WIRELESS_NETWORK_DIR}/*${hash}" + + if [ -d "${path}" ]; then + basename "${path}" + else + local normalized=$(normalize "${string}") + normalized=${normalized%-} + echo "${normalized}-${hash}" + fi +} + +wireless_network_new() { + if [ $# -gt 1 ]; then + error "Too many arguments" + return ${EXIT_ERROR} + fi + + local ssid="${1}" + if ! isset ssid; then + error "Please provide a SSID" + return ${EXIT_ERROR} + fi + + local ssid_hash="$(wireless_network_hash "${ssid}")" + assert isset ssid_hash + + # Check for duplicates + if wireless_network_exists "${ssid}"; then + error "The wireless network ${ssid} already exists" + return ${EXIT_ERROR} + fi + + log DEBUG "Creating wireless network '${ssid}'" + + if ! mkdir -p "${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}"; then + log ERROR "Could not create config directory for wireless network ${ssid}" + return ${EXIT_ERROR} + fi + + # When the ssid is not set in the settings file we cannot write it because wireless_network_exists fails + echo "SSID=\"${ssid}\"" >>"${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}/settings" + + local ${WIRELESS_NETWORK_CONFIG_SETTINGS} + SSID="${ssid}" + PRIORITY=500 + + if ! wireless_network_write_config "${ssid}"; then + log ERROR "Could not write new config file" + return ${EXIT_ERROR} + fi +} + +# Function that deletes based on the passed parameters +# one ore more wireless networks +wireless_network_destroy() { + local ssid + for ssid in "$@"; do + local ssid_hash="$(wireless_network_hash "${ssid}")" + assert isset ssid_hash + + if ! wireless_network_exists "${ssid}"; then + log ERROR "The wireless network ${ssid} does not exist." + continue + fi + + log DEBUG "Deleting wireless network ${ssid}" + + if ! rm -rf "${NETWORK_WIRELESS_NETWORK_DIR}/${ssid_hash}"; then + log ERROR "Deleting the wireless network ${ssid} was not sucessful" + return ${EXIT_ERROR} + fi + done +} + +wireless_network_encryption_mode() { + if [ ! $# -eq 2 ]; then + log ERROR "Not enough arguments" + return ${EXIT_ERROR} + fi + local ssid="${1}" + local mode="${2}" + + if ! isoneof mode ${WIRELESS_NETWORKS_VALID_ENCRYPTION_MODES}; then + log ERROR "Encryption mode '${mode}' is invalid" + return ${EXIT_ERROR} + fi + + if ! wireless_network_write_config_key "${ssid}" "ENCRYPTION_MODE" ${mode^^}; then + log ERROR "Could not write configuration settings" + return ${EXIT_ERROR} + fi +} + +wireless_network_key() { + if [ ! $# -eq 2 ]; then + log ERROR "Not enough arguments" + return ${EXIT_ERROR} + fi + local ssid="${1}" + local key="${2}" + + if ! wireless_network_write_config_key "${ssid}" "KEY" "${key}"; then + log ERROR "Could not write configuration settings" + return ${EXIT_ERROR} + fi +} + +wireless_network_priority() { + if [ ! $# -eq 2 ]; then + log ERROR "Not enough arguments" + return ${EXIT_ERROR} + fi + local ssid="${1}" + local priority=${2} + + if ! isinteger priority && [ ! ${priority} -ge 0 ]; then + log ERROR "The priority must be an integer greater or eqal zero" + return ${EXIT_ERROR} + fi + + if ! wireless_network_write_config_key "${ssid}" "PRIORITY" "${priority}"; then + log ERROR "Could not write configuration settings" + return ${EXIT_ERROR} + fi +} diff --git a/src/network b/src/network index 71b0cdec..9a2d4809 100644 --- a/src/network +++ b/src/network @@ -1367,7 +1367,7 @@ case "${action}" in init_run ;; - settings|hostname|port|device|zone|start|stop|restart|status|reset|route|vpn) + settings|hostname|port|device|zone|start|stop|restart|status|reset|route|vpn|wireless) cli_${action} "$@" ;; -- 2.39.2