]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/hooks/ports/wireless-ap
wireless-ap: Allow setting the wireless environment (indoor/outdoor)
[people/ms/network.git] / src / hooks / ports / wireless-ap
old mode 100755 (executable)
new mode 100644 (file)
index c6d91da..6db39b8
 
 . /usr/lib/network/header-port
 
-HOOK_SETTINGS="HOOK ADDRESS BROADCAST_SSID CHANNEL COUNTRY_CODE MODE PHY SSID"
-HOOK_SETTINGS="${HOOK_SETTINGS} ENCRYPTION KEY"
+HOOK_PORT_PATTERN="${PORT_PATTERN_ACCESSPOINT}"
+
+HOOK_SETTINGS="ADDRESS BROADCAST_SSID CHANNEL CHANNEL_BANDWIDTH DFS MODE PHY"
+HOOK_SETTINGS="${HOOK_SETTINGS} ENCRYPTION ENVIRONMENT KEY SSID"
 
 ADDRESS=$(mac_generate)
 BROADCAST_SSID=on
-CHANNEL=1
-COUNTRY_CODE="US"
+CHANNEL=
+CHANNEL_BANDWIDTH=
 ENCRYPTION=""
 KEY=""
-MODE="g"
 SSID=
 
-function hook_check() {
+# Perform radar detection by default when possible
+DFS="on"
+
+ENVIRONMENT="${WIRELESS_DEFAULT_ENVIRONMENT}"
+
+hook_check_settings() {
        assert isset ADDRESS
        assert ismac ADDRESS
        assert isset BROADCAST_SSID
        assert isbool BROADCAST_SSID
        assert isset CHANNEL
-       assert isset COUNTRY_CODE
+       assert isbool DFS
        assert isset MODE
-       assert isoneof MODE a b g n
+       assert isoneof MODE ${HOSTAPD_SUPPORTED_MODES}
        assert isset PHY
        assert ismac PHY
        assert isset SSID
@@ -53,37 +59,65 @@ function hook_check() {
                assert [ ${#KEY} -ge 8 ]
                assert [ ${#KEY} -le 63 ]
        fi
+
+       assert wireless_environment_is_valid "${ENVIRONMENT}"
 }
 
-function hook_create() {
+hook_parse_cmdline() {
        while [ $# -gt 0 ]; do
                case "${1}" in
                        --broadcast-ssid=*)
-                               BROADCAST_SSID=$(cli_get_val ${1})
+                               BROADCAST_SSID=$(cli_get_val "${1}")
                                ;;
                        --channel=*)
-                               CHANNEL=$(cli_get_val ${1})
+                               CHANNEL=$(cli_get_val "${1}")
                                ;;
-                       --country-code=*)
-                               COUNTRY_CODE=$(cli_get_val ${1})
+                       --channel-bandwidth=*)
+                               CHANNEL_BANDWIDTH="$(cli_get_val "${1}")"
+                               ;;
+                       --dfs=*)
+                               DFS="$(cli_get_val "${1}")"
+
+                               if enabled DFS; then
+                                       DFS="on"
+                               elif disabled DFS; then
+                                       DFS="off"
+                               else
+                                       error "Invalid value for DFS: ${DFS}"
+                                       return ${EXIT_ERROR}
+                               fi
                                ;;
                        --encryption=*)
-                               ENCRYPTION=$(cli_get_val ${1})
+                               ENCRYPTION=$(cli_get_val "${1}")
+                               ;;
+                       --environment=*)
+                               ENVIRONMENT="$(cli_get_val "${1}")"
+
+                               if ! wireless_environment_is_valid "${ENVIRONMENT}"; then
+                                       error "Invalid wireless environment: ${ENVIRONMENT}"
+                                       return ${EXIT_ERROR}
+                               fi
                                ;;
                        --key=*)
-                               KEY=$(cli_get_val ${1})
+                               KEY=$(cli_get_val "${1}")
                                ;;
                        --mac=*)
-                               ADDRESS=$(cli_get_val ${1})
+                               ADDRESS=$(cli_get_val "${1}")
                                ;;
                        --mode=*)
-                               MODE=$(cli_get_val ${1})
+                               MODE=$(cli_get_val "${1}")
+
+                               if ! isoneof MODE ${HOSTAPD_SUPPORTED_MODES}; then
+                                       error "Unsupported mode: ${MODE}"
+                                       error "Mode must be one of ${HOSTAPD_SUPPORTED_MODES}"
+                                       return ${EXIT_ERROR}
+                               fi
                                ;;
                        --phy=*)
-                               PHY=$(cli_get_val ${1})
+                               PHY=$(cli_get_val "${1}")
                                ;;
                        --ssid=*)
-                               SSID=$(cli_get_val ${1})
+                               SSID=$(cli_get_val "${1}")
                                ;;
                        *)
                                warning "Ignoring unknown argument '${1}'"
@@ -92,66 +126,54 @@ function hook_create() {
                shift
        done
 
-       # Save address of phy do identify it again
-       PHY=$(phy_get ${PHY})
-       PHY=$(phy_get_address ${PHY})
+       # Generate a random MAC address if none is set
+       if ! isset ADDRESS; then
+               ADDRESS="$(mac_generate)"
+       fi
 
-       local port=$(port_find_free ${PORT_PATTERN_ACCESSPOINT})
-       assert isset port
+       # MODE must be set
+       if ! isset MODE; then
+               error "--mode is not set"
+               return ${EXIT_ERROR}
+       fi
 
-       config_write $(port_file ${port}) ${HOOK_SETTINGS}
+       # Automatically enable ACS if no channel is set and ACS is available
+       if ! isset CHANNEL && phy_supports_acs "${PHY}"; then
+               CHANNEL="0"
 
-       exit ${EXIT_OK}
+               log INFO "Automatic Channel Selection (ACS) enabled"
+       fi
+
+       # Channel bandwidth must match the mode
+       if isset CHANNEL_BANDWIDTH && ! wireless_channel_bandwidth_is_valid "${MODE}" "${CHANNEL_BANDWIDTH}"; then
+               error "Channel Bandwidth '${CHANNEL_BANDWIDTH}' is not supported for ${MODE}"
+               return ${EXIT_ERROR}
+       fi
+
+       # Save address of phy do identify it again
+       PHY=$(phy_get ${PHY})
+       PHY=$(phy_get_address ${PHY})
 }
 
-function hook_edit() {
+hook_edit() {
        local port=${1}
-       shift
-
        assert isset port
 
-       config_read $(port_file ${port})
-
-       while [ $# -gt 0 ]; do
-               case "${1}" in
-                       --broadcast-ssid=*)
-                               BROADCAST_SSID=$(cli_get_val ${1})
-                               ;;
-                       --channel=*)
-                               CHANNEL=$(cli_get_val ${1})
-                               ;;
-                       --country-code=*)
-                               COUNTRY_CODE=$(cli_get_val ${1})
-                               ;;
-                       --encryption=*)
-                               ENCRYPTION=$(cli_get_val ${1})
-                               ;;
-                       --key=*)
-                               KEY=$(cli_get_val ${1})
-                               ;;
-                       --ssid=*)
-                               SSID=$(cli_get_val ${1})
-                               ;;
-                       --mode=*)
-                               MODE=$(cli_get_val ${1})
-                               ;;
-                       *)
-                               warning "Unknown argument '${1}'"
-                               ;;
-               esac
-               shift
-       done
-
-       config_write $(port_file ${port}) ${HOOK_SETTINGS}
+       if ! hook_default_edit "$@"; then
+               return ${EXIT_ERROR}
+       fi
 
-       exit ${EXIT_OK} 
+       # To apply all changes, we need to restart the port
+       port_restart "${port}"
 }
 
-function hook_up() {
-       local port=${1}
+hook_create() {
+       local port="${1}"
        assert isset port
 
-       config_read $(port_file ${port})
+       device_exists "${port}" && exit ${EXIT_OK}
+
+       port_settings_read "${port}" ${HOOK_SETTINGS}
 
        # Check if the PHY is present.
        local phy=$(phy_get ${PHY})
@@ -160,60 +182,67 @@ function hook_up() {
                exit ${EXIT_ERROR}
        fi
 
-       # Create the wireless device, if it does not exist, yet.
-       if ! device_exists ${port}; then
-               wireless_create ${port} --phy="${phy}" --type="ap" \
-                       --address="${ADDRESS}"
-       fi
-
-       # Start the hostapd service.
-       hostapd_start ${port}
-       local ret=$?
-
-       if [ ${ret} -ne ${EXIT_OK} ]; then
-               log ERROR "Could not start hostapd on port '${port}': ${ret}"
-               exit ${EXIT_ERROR}
-       fi
+       # Create the wireless device
+       wireless_create "${port}" \
+               --phy="${phy}" \
+               --type="ap" \
+               --address="${ADDRESS}"
 
        exit ${EXIT_OK}
 }
 
-function hook_down() {
-       local port=${1}
+hook_remove() {
+       local port="${1}"
        assert isset port
 
-       # Stop the hostapd daemon.
-       hostapd_stop ${port}
-
-       # Remove the device if it is still present.
-       if device_exists ${port}; then
-               wireless_remove ${port}
+       # Remove the device if present
+       if device_exists "${port}"; then
+               wireless_remove "${port}"
        fi
 
        exit ${EXIT_OK}
 }
 
-function hook_hotplug() {
-       local port=${1}
+hook_up() {
+       local port="${1}"
        assert isset port
 
-       local phy=${2}
-       assert isset phy
+       # The port must already exist before
+       # hostapd is started. Otherwise it will
+       # fail horribly over and over again.
+       assert device_exists "${port}"
 
-       assert port_exists ${port}
+       hostapd_start "${port}"
+}
 
-       # Read configuration of port.
-       config_read $(port_file ${port})
+hook_down() {
+       local port="${1}"
+       assert isset port
 
-       # Get the address of the phy.
-       local phy_address=$(phy_get_address ${phy})
+       hostapd_stop "${port}"
+}
 
-       # Check if the phy is the same we have
-       # read from the configuration file.
-       if [ "${PHY}" = "${phy_address}" ]; then
-               wireless_create ${port} --phy="${phy_address}" --type="ap" \
-                       --address="${ADDRESS}"
-       fi
+hook_hotplug() {
+       local port="${1}"
+       assert isset port
 
-       exit ${EXIT_OK}
+       case "$(hotplug_action)" in
+               add)
+                       # Create the port when the phy is plugged in
+                       if hotplug_event_port_uses_phy "${port}"; then
+                               hook_create "${port}"
+                       fi
+                       ;;
+
+               remove)
+                       # Stop hostapd
+                       if hotplug_event_port_is_interface "${port}"; then
+                               hostapd_stop "${port}"
+
+                               exit ${EXIT_OK}
+                       fi
+                       ;;
+       esac
+
+       exit ${EXIT_NOT_HANDLED}
 }