. /usr/lib/network/header-port
-HOOK_SETTINGS="HOOK ADDRESS BROADCAST_SSID CHANNEL 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
+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 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
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}")
+ ;;
+ --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}'"
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
- port_settings_write "${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
- port_settings_read "${port}" ${HOOK_SETTINGS}
-
- while [ $# -gt 0 ]; do
- case "${1}" in
- --broadcast-ssid=*)
- BROADCAST_SSID=$(cli_get_val ${1})
- ;;
- --channel=*)
- CHANNEL=$(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
-
- port_settings_write "${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
+ device_exists "${port}" && exit ${EXIT_OK}
+
port_settings_read "${port}" ${HOOK_SETTINGS}
# Check if the PHY is present.
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
# Remove the device if present
exit ${EXIT_OK}
}
-function hook_hotplug() {
+hook_up() {
+ local port="${1}"
+ assert isset port
+
+ # The port must already exist before
+ # hostapd is started. Otherwise it will
+ # fail horribly over and over again.
+ assert device_exists "${port}"
+
+ hostapd_start "${port}"
+}
+
+hook_down() {
+ local port="${1}"
+ assert isset port
+
+ hostapd_stop "${port}"
+}
+
+hook_hotplug() {
local port="${1}"
assert isset port
case "$(hotplug_action)" in
add)
- # Start hostapd after the port has been brought up
- if hotplug_event_port_is_interface "${port}"; then
- hostapd_start "${port}"
-
- # Bring up the port when the phy is plugged in
- elif hotplug_event_port_uses_phy "${port}"; then
- hook_up "${port}"
+ # Create the port when the phy is plugged in
+ if hotplug_event_port_uses_phy "${port}"; then
+ hook_create "${port}"
fi
;;
# Stop hostapd
if hotplug_event_port_is_interface "${port}"; then
hostapd_stop "${port}"
- fi
- ;;
- *)
- exit ${EXIT_NOT_HANDLED}
+ exit ${EXIT_OK}
+ fi
;;
esac
- exit ${EXIT_OK}
+ exit ${EXIT_NOT_HANDLED}
}