#!/bin/sh /etc/rc.common # Copyright (c) 2015, 2017-2018 Qualcomm Technologies, Inc. # # All Rights Reserved. # Confidential and Proprietary - Qualcomm Technologies, Inc. # # 2015 Qualcomm Atheros, Inc. # # All Rights Reserved. # Qualcomm Atheros Confidential and Proprietary. # shellcheck disable=SC2034 START=97 # needs to be after LED init # shellcheck disable=SC2034 SERVICE_WRITE_PID=1 # shellcheck disable=SC2034 SERVICE_DAEMONIZE=1 #SERVICE_DEBUG=1 NETWORK_RESTART=0 SERVICE_DEBUG_OUTPUT=0 REPACD_DEBUG_OUTOUT=0 # These restart_in_*_mode commands are only intended to be used by # repacd-run.sh. # # - restart_in_cap_mode is used when the device has a direct connection to the # the gateway via ethernet. This will result in only the AP interfaces being # enabled. # - restart_in_noncap_mode is used when the device no longer has a direct # connection to the gateway via ethernet. When this is done, the device will # either have both its AP and STA interfaces enabled (if its primary purpose # is as a standalone RE) or just its STA interface enabled (if its primary # purpose is as a client device). # - restart_in_re_mode is used when a device that is intended to primarily # act as a client actually has sufficient link quality to act as a range # extender. It will enable both the STA and AP interfaces. EXTRA_COMMANDS="restart_in_cap_mode restart_in_noncap_mode restart_in_re_mode" EXTRA_HELP=< /dev/console else echo "whc (repacd): $*" fi } # Determine if the device is configured in gateway mode or not. # Note that a device can still act as a CAP even if it is not in gateway # mode, but this is detected later by the repacd-run.sh script. # # return: 0 if in gateway mode; otherwise non-zero __repacd_gw_mode() { local wan_iface config_load network config_get wan_iface wan ifname [ -n "$wan_iface" ] && return 0 return 1 } # Determine if the network is configured or not. # # input: $1 network name # return: 0 if network exist; otherwise non-zero __repacd_network_exist() { local lan_name=$1 local no_network no_network=$(uci show "network.$lan_name" 2>&1 | grep 'Entry not found') [ -n "$no_network" ] && return 1 return 0 } # Set bridge_empty option for the given network. # This option allows to create empty_bridge. # # input: $1 network name __repacd_set_bridge_empty() { local name="$1" local bridge_empty config_load network config_get bridge_empty "$name" 'bridge_empty' 0 if [ "$bridge_empty" -eq 0 ]; then uci_set network "$name" bridge_empty '1' fi uci_commit network } # Determine if additional network exist. # Currently looking out for only guest network. # # input: $1 network name # return: 0 if exist; otherwise non-zero __repacd_check_additional_network_exist() { config_load network if [ -n "$network_guest" ]; then if __repacd_network_exist $network_guest; then return 0 fi fi return 1 } # Add the given interface to the given network. # input: $1 network name # input: $2 interface name __repacd_add_interface() { local name=$1 new_if="$2" local if_name if __repacd_network_exist "$name"; then if [ -n "$new_if" ]; then if_name=$(uci get "network.$name.ifname") if [ -n "$if_name" ]; then if_name="$if_name $new_if" else if_name="$new_if" fi if_name=$(echo "$if_name" | xargs -n1 | sort -u | xargs) uci_set network "$name" ifname "$if_name" fi fi } # Get backhaul interfaces for ethernet. # output: $1 - variable into which we populate interface(eth0.102 or eth1.102). __repacd_get_backhaul_ifaces_eth_guest() { local ifaces local ifaces_guest_intf ifaces=$(ifconfig 2>&1 | grep eth | grep $guest_vid) ifaces_guest_intf=$(echo "$ifaces" | cut -d ' ' -f1) eval "$1='$ifaces_guest_intf'" } # Delete the given interface from the given network. # input: $1 network name # input: $2 interface name __repacd_delete_interface() { local name=$1 interface="$2" local if_name if __repacd_network_exist "$name"; then if [ -n "$interface" ]; then if_name=$(uci get "network.$name.ifname") if [ -n "$if_name" ]; then if_name=${if_name/$interface/} fi uci_set network "$name" ifname "$if_name" fi fi } # Create necessary VLAN interfaces for the backhaul vaps and add the # created VLAN interfaces to the given network. # VLAN interfaces are created by concatenating interface name and vlan id. # input: $1 name of the interface config section # input: $2 network name # input: $3 VLAN id # input: $4 Band '2.4G' or '5G' or 'both' # input-output: $5 change counter __repacd_add_vlan_interfaces() { local config=$1 local id=$3 local backhaul_iface=$4 local changed="$5" local ifname vlan_ifname local disabled mode bssid device hwmode local add_vlan=0 config_get network "$config" network config_get ifname "$config" ifname config_get disabled "$config" disabled '0' config_get mode "$config" mode config_get device "$config" device config_get hwmode "$device" hwmode if [ "$hwmode" != "11ad" ]; then if [ "$network" = "$network_backhaul" ] && [ -n "$ifname" ] && \ [ "$disabled" -eq 0 ]; then vlan_ifname=$(iwconfig 2>&1 | grep "$ifname.$id" | cut -d ' ' -f1) if [ -z "$vlan_ifname" ]; then if [ "$backhaul_iface" = 'both' ] || [ "$mode" = "ap" ]; then add_vlan=1 elif [ "$backhaul_iface" = '5G' ] && \ [ "$hwmode" = '11ac' ] || [ "$hwmode" = '11na' ] || [ "$hwmode" = '11a' ]; then add_vlan=1 elif [ "$backhaul_iface" = '2.4G' ] && \ [ "$hwmode" = '11ng' ] || [ "$hwmode" = '11g' ] || [ "$hwmode" = '11b' ]; then add_vlan=1 fi if [ "$add_vlan" -gt 0 ]; then vconfig add "$ifname" "$id" brctl addif "br-$2" "$ifname.$id" ifconfig "$ifname.$id" up __repacd_add_interface "$2" "$ifname.$id" changed=$((changed + 1)) eval "$5='$changed'" fi fi fi fi } # Delete VLAN interfaces of backhaul vaps. # input: $1 name of the interface config section # input: $2 network name # input: $3 VLAN id # input: $4 mode 'sta' or 'ap' # input-output: $5 change counter __repacd_delete_vlan_interfaces() { local config=$1 local id=$3 local changed="$5" local ifname vlan_ifname local disabled mode bssid device hwmode config_get network "$config" network config_get ifname "$config" ifname config_get disabled "$config" disabled '0' config_get mode "$config" mode config_get device "$config" device config_get hwmode "$device" hwmode if [ "$hwmode" != "11ad" ]; then if [ "$network" = "$network_backhaul" ] && [ -n "$ifname" ] && \ [ "$disabled" -eq 0 ]; then vlan_ifname=$(iwconfig 2>&1 | grep "$ifname.$id" | cut -d ' ' -f1) if [ -n "$vlan_ifname" ]; then if __repacd_is_matching_mode "$4" "$mode"; then vconfig rem "$ifname.$id" brctl delif "br-$2" "$ifname.$id" __repacd_delete_interface "$2" "$ifname.$id" changed=$((changed + 1)) eval "$5='$changed'" fi fi fi fi } #Create Back haul interface for ethernet guest network and #add it to the respective bridge #input:$1 guest network name #input-output:$2 change counter __repacd_add_ethernet_vlan_interfaces() { local backhaul_ifaces_eth local network=$1 local changed="$2" __repacd_get_backhaul_ifaces_eth_guest backhaul_ifaces_eth if [ -n "$backhaul_ifaces_eth" ]; then __repacd_echo "Add VLAN ifaces for ethernet guest network support" if [ "$backhaul_ifaces_eth" = "$eth_iface_wan.$guest_vid" ] && [ "$network" = 'guest' ];then swconfig dev switch0 vlan $guest_vid set ports "0t ${eth_iface_wan_port}t ${eth_iface_lan_port1}t" swconfig dev switch0 set apply brctl addif "br-$network" "$backhaul_ifaces_eth" ifconfig "$backhaul_ifaces_eth" up __repacd_add_interface "$network" "$backhaul_ifaces_eth" elif [ "$backhaul_ifaces_eth" = "$eth_iface_lan.$guest_vid" ] && [ "$network" = 'guest' ];then swconfig dev switch0 vlan $guest_vid set ports "0t ${eth_iface_lan_port1}t ${eth_iface_lan_port2}t" swconfig dev switch0 set apply brctl addif "br-$network" "$backhaul_ifaces_eth" ifconfig "$backhaul_ifaces_eth" up __repacd_add_interface "$network" "$backhaul_ifaces_eth" else __repacd_echo "For Home network all the traffic is untagged,no vlan" fi #Do we really need to restart? revisit this changed=$((changed + 1)) eval "$2='$changed'" fi } # Create firewall rules for the given network if the rule does not exist. # input: $1 network name __repacd_set_firewall_rules() { local network=$1 local no_rule local rule_name no_rule=$(uci show firewall | grep zone | grep "$network") if [ -z "$no_rule" ]; then local zone zone=$(uci add firewall zone) if [ -n "$zone" ]; then uci_set firewall "$zone" name "$network" uci add_list "firewall.$zone.network=$network" uci_set firewall "$zone" input 'REJECT' uci_set firewall "$zone" output 'ACCEPT' uci_set firewall "$zone" forward 'REJECT' local fwd fwd=$(uci add firewall forwarding) if [ -n "$fwd" ]; then uci_set firewall "$fwd" src "$network" uci_set firewall "$fwd" dest 'wan' fi local rule rule=$(uci add firewall rule) if [ -n "$rule" ]; then uci_set firewall "$rule" name 'Allow-DHCP-request' uci_set firewall "$rule" src "$network" uci_set firewall "$rule" src_port '67-68' uci_set firewall "$rule" dest_port '67-68' uci_set firewall "$rule" proto 'udp' uci_set firewall "$rule" target 'ACCEPT' fi rule=$(uci add firewall rule) if [ -n "$rule" ]; then uci_set firewall "$rule" name 'Allow-DNS-queries' uci_set firewall "$rule" src "$network" uci_set firewall "$rule" dest_port '53' uci_set firewall "$rule" proto 'tcpudp' uci_set firewall "$rule" target 'ACCEPT' fi rule=$(uci add firewall rule) if [ -n "$rule" ]; then rule_name="Block-$managed_network-$network-forwarding" uci_set firewall "$rule" name "$rule_name" uci_set firewall "$rule" src $managed_network uci_set firewall "$rule" dest "$network" uci_set firewall "$rule" proto '0' uci_set firewall "$rule" family 'any' uci_set firewall "$rule" target 'REJECT' fi rule=$(uci add firewall rule) if [ -n "$rule" ]; then rule_name="Block-$network-$managed_network-forwarding" uci_set firewall "$rule" name "$rule_name" uci_set firewall "$rule" src "$network" uci_set firewall "$rule" dest $managed_network uci_set firewall "$rule" proto '0' uci_set firewall "$rule" family 'any' uci_set firewall "$rule" target 'REJECT' fi fi fi uci_commit firewall } # Restart firewall. __repacd_restart_firewall() { /etc/init.d/firewall restart } # Check whether the given interface is the backhaul AP interface on # the desired network and update the band specific interface names. # # input: $1 - config: the name of the interface config section # input: $2 - network: the name of the network to which the AP interface # must belong to be matched # output: $3 - iface: the resolved backhaul AP interface name on 2.4 GHz (if found) # output: $4 - iface: the resolved backhaul AP interface name on 5 GHz (if found) __repacd_wifi_check_and_get_backhaul_ap_iface() { local config="$1" local network_to_match="$2" local iface disabled mode device hwmode backhaul_ap config_get network "$config" network config_get iface "$config" ifname config_get disabled "$config" disabled '0' config_get mode "$config" mode config_get device "$config" device config_get backhaul_ap "$config" backhaul_ap '0' config_get hwmode "$device" hwmode if [ "$hwmode" != "11ad" ]; then if [ "$network" = "$network_to_match" ] && [ -n "$iface" ] && [ "$mode" = "ap" ] \ && [ "$backhaul_ap" -gt 0 ] && [ "$disabled" -eq 0 ]; then if whc_is_5g_vap "$config"; then eval "$4=$iface" else eval "$3=$iface" fi fi fi } # Configure the otherband BSSIDs for both backhaul APs # input: $1 - network: the name of the network to which the AP interface # must belong to be matched # output: None __repacd_wifi_set_otherband_bssids() { local otherband_bssid1 otherband_bssid2 bssid_5g bssid_24g local backhaul_ap_iface_24g backhaul_ap_iface_5g success=0 loop_count=15 while [ "$success" -eq 0 ] && [ "$loop_count" -gt 0 ]; do config_load wireless config_foreach __repacd_wifi_check_and_get_backhaul_ap_iface wifi-iface "$1" \ backhaul_ap_iface_24g backhaul_ap_iface_5g if [ -n "$backhaul_ap_iface_5g" ] && [ -n "$backhaul_ap_iface_24g" ]; then bssid_5g=$(ifconfig "$backhaul_ap_iface_5g" | grep "HWaddr" | awk -F" " '{print $5}') bssid_24g=$(ifconfig "$backhaul_ap_iface_24g" | grep "HWaddr" | awk -F" " '{print $5}') otherband_bssid1=$(echo "$bssid_5g" | sed -e "s/://g" | cut -b 1-8) otherband_bssid2=$(echo "$bssid_5g" | sed -e "s/://g" | cut -b 9-12) if [ -z $REPACD_CFG80211 ]; then iwpriv $backhaul_ap_iface_24g otherband_bssid 0x$otherband_bssid1 0x$otherband_bssid2 else cfg80211tool $backhaul_ap_iface_24g otherband_bssid 0x$otherband_bssid1 0x$otherband_bssid2 fi otherband_bssid1=$(echo "$bssid_24g" | sed -e "s/://g" | cut -b 1-8) otherband_bssid2=$(echo "$bssid_24g" | sed -e "s/://g" | cut -b 9-12) if [ -z $REPACD_CFG80211 ]; then iwpriv $backhaul_ap_iface_5g otherband_bssid 0x$otherband_bssid1 0x$otherband_bssid2 else cfg80211tool $backhaul_ap_iface_5g otherband_bssid 0x$otherband_bssid1 0x$otherband_bssid2 fi success=1 else sleep 1 loop_count=$((loop_count - 1)) fi done } # Enumerate all of the wifi interfaces and append # only station devices to the variable provided. # output: $1 devices: variable to populate with the station devices __repacd_get_sta_devices() { local devices=$1 config_cb() { local type="$1" local section="$2" case "$type" in wifi-iface) config_get mode "$section" mode config_get device "$section" device if [ "$mode" = 'sta' ];then eval append $devices "$device" fi ;; esac } config_load wireless } # Configure the vap independent parameter for given wifi interface. # # input: $1 - config: interface config name to configure. # input: $2 - devices: list of devices to match with provided interface. __repacd_config_vap_ind() { local config=$1 local devices=$2 local match_found=0 local device config_load wireless config_get device "$config" device for device_to_match in $devices; do if [ "$device" = "$device_to_match" ]; then if __repacd_is_son_mode; then # If in SON mode, STA vaps may be forced down based on # link strength so configure the VAPs in independent mode. # This will be used in conjunction with the other feature # that monitors the backhaul links and brings down the AP VAPs # if there is no backhaul for a sustained period of time. __repacd_update_vap_param "$config" 'athnewind' 1 else __repacd_update_vap_param "$config" 'athnewind' 0 fi match_found=1 fi done # If the feature Manage Front-Haul VAPs independently based on # CAP's reachability is enabled, then set athnewind value to 1. if [ "$Manage_front_and_back_hauls_ind" -gt 0 ]; then __repacd_update_vap_param "$config" 'athnewind' 1 # This is mainly for wsplcd optimization: if wsplcd detects athnewind # is set to 0, it will not restart VAP; otherwise it will bring down # the VAP, set athnewind to 0 and bring the VAP back up elif [ "$match_found" -eq 0 ]; then __repacd_update_vap_param "$config" 'athnewind' 0 fi } # Configure the vap independent parameter for all VAPs # only if repacd is allowed to configure this parameter. # input: None __repacd_config_independent_vaps() { local sta_devices= if [ "$manage_vap_ind" -gt 0 ]; then __repacd_get_sta_devices sta_devices __repacd_echo "Station device list = $sta_devices" config_foreach __repacd_config_vap_ind wifi-iface "$sta_devices" else # Pass empty device list, so that all vaps set to athnewind=0. config_foreach __repacd_config_vap_ind wifi-iface "$sta_devices" fi } # Determine the configured RE mode, not applying any automatic mode # switching rules. # # output: $1 variable in which to place the resolved mode __repacd_get_config_re_mode() { local resolved_mode=$1 local mode config_load 'repacd' config_get mode repacd 'ConfigREMode' 'auto' eval "$resolved_mode=$mode" } # Determine whether the provided mode is an automatic mode. # # input: $1 mode: the mode to check # return: 0 if the mode is an auto mode; otherwise 1 __repacd_is_auto_re_mode() { local mode=$1 if [ "$mode" = 'auto' ]; then return 0 fi return 1 } # Resolve the current mode in which to operate the range extender. # # This mode is either the configured mode (if it is set to a specific # mode), the automatically derived RE mode based on association information, # or the default range extender mode for use at startup. # # output: $1 - the variable into which to place the resolved mode __repacd_get_re_mode() { local resolved_mode=$1 local mode default_mode __repacd_get_config_re_mode config_re_mode if __repacd_is_auto_re_mode $config_re_mode; then config_get default_mode repacd 'DefaultREMode' 'qwrap' config_get mode repacd 'AssocDerivedREMode' "$default_mode" else mode=$config_re_mode fi # Get the Association derived sub-mode. If not derived, say "star". config_get resolved_re_submode repacd 'AssocDerivedRESubMode' 'star' eval "$resolved_mode=$mode" } # Determine if the range extension mode is set to WDS. # # return: 0 if the mode is set to WDS; otherwise 1 (meaing QWrap or ExtAP) __repacd_is_wds_mode() { __repacd_get_re_mode resolved_re_mode case "$resolved_re_mode" in wds|WDS) return 0 ;; *) return 1 ;; esac } # Determine if the range extension mode is set to QWrap. # # return: 0 if the mode is set to QWrap; otherwise 1 (meaning WDS or ExtAP) __repacd_is_qwrap_mode() { __repacd_get_re_mode resolved_re_mode case "$resolved_re_mode" in qwrap|QWRAP) return 0 ;; *) return 1 esac } # Determine if the range extension mode is set to SON. # Note that if the hyd init script is missing, this will be considered as # SON mode disabled. # # return: 0 if the mode is set to SON; otherwise 1 (meaing WDS or an # interoperable range extension mode) __repacd_is_son_mode() { if [ ! -f $HYD_INIT ]; then return 1 fi __repacd_get_re_mode resolved_re_mode case "$resolved_re_mode" in son|SON) return 0 ;; *) return 1 ;; esac } # Determine whether the Multi-AP Topology Optimization algorithm is enabled. # # return: 0 if the algorithm is enabled; otherwise 1 __repacd_is_map_enabled() { local map_enabled config_load 'repacd' config_get_bool map_enabled MAPConfig 'Enable' '0' [ "$map_enabled" -gt 0 ] return $? } # Determine if DFS channels are to be blocked even for WDS mode. # # return: 0 if DFS channels should not be used; otherwise 1 (meaning they may # be used) __repacd_is_block_dfs() { local block_dfs config_load 'repacd' config_get block_dfs repacd 'BlockDFSChannels' '0' if [ "$block_dfs" -gt 0 ]; then return 0 else return 1 fi } # Get the configured Rate scaling factor. # Gives default value in case of configuration miss or invalid value. # # output: $1 - rate_scaling_factor __repacd_get_rate_scaling_factor() { local scaling_factor config_load 'repacd' config_get scaling_factor WiFiLink 'RateScalingFactor' $RE_DEFAULT_RATE_ESTIMATE_SCALING_FACTOR # If scaling factor out of limits, return the default value "70". if [ "$scaling_factor" -lt '1' ] || \ [ "$scaling_factor" -gt '100' ]; then scaling_factor=$RE_DEFAULT_RATE_ESTIMATE_SCALING_FACTOR fi eval "$1=$scaling_factor" } # check vap is in default configuration by comparing ssid as OpenWrt # and encryption as none,for now any one VAP with this configuration # is enough for marking configuration as default configuration. # Internal driver currently does not support 11ad so ignoring # 11ad enabled devices for now. # input: $1 config: section to update # input: $2 network: Global variable vap_defconf. # input-output:$2 is set to '0' in case we have any VAP # with default config. __repacd_check_default_vaps() { local config="$1" config_get device "$config" device config_get ssid "$config" ssid config_get encryption "$config" encryption config_get hwmode "$device" hwmode config_get type "$device" type config_get_bool repacd_security_unmanaged "$config" repacd_security_unmanaged '0' if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] ;then return fi if [ "$repacd_security_unmanaged" -eq 1 ] ; then return fi if [ "$ssid" = "OpenWrt" ] && [ "$encryption" = "none" ] ;then eval "$2='0'" fi } # Determine if the VAPs are in the default configuration. # For now this is defined simply as any VAP having the default SSID and no # security enabled or that there are no VAPs whatsoever. # # return: 0 if in the default configuration; otherwise non-zero __repacd_vaps_in_default_config() { local no_vaps # If there is no entry, uci will give an error message. We detect this # by looking for the string in the output. no_vaps=$(uci show wireless.@wifi-iface[-1] 2>&1 | grep 'Entry not found') [ -n "$no_vaps" ] && return 0 config_load wireless config_foreach __repacd_check_default_vaps wifi-iface vap_defconf return $vap_defconf } # Generate a suffix for the SSID using the last 3 bytes of the MAC address # on the bridge that is being managed. # # output: $1 - variable into which to write the SSID suffix __repacd_generate_ssid_suffix() { local generated_suffix generated_suffix=$(ifconfig br-$managed_network | grep HWaddr | awk '{print $5}' | awk -F":" '{print $4$5$6}') eval "$1=$generated_suffix" } # Generate a random pre-shared key for use with WPA2 # # output: $1 - variable into which to write the PSK __repacd_generate_psk() { local generated_key generated_key=$(dd if=/dev/urandom bs=1 count=8 2> /dev/null | openssl base64) eval "$1=$generated_key" } # Reconfigure all managed VAPs and create new ones as appropriate. This is # non-destructive in that all configuration parameters for a VAP that are not # directly controlled by this script will not be modified. # # This should generally only be called when starting with a fresh # configuration (eg. at first boot or due to a user request), as it will # generate an SSID and passphrase. See __repacd_reset_existing_config() for # the function used when the SSID and passphrase configured are to be # preserved. __repacd_reset_default_config() { config_load wireless config_foreach __repacd_resolve_vaps wifi-iface $managed_network # Use last three bytes of the MAC address to help make the SSID unique. local ssid_suffix __repacd_generate_ssid_suffix ssid_suffix # Generate a random password (which will likely be changed either through # cloning or by the end user). local random_psk __repacd_generate_psk random_psk __repacd_create_vaps "whc-$ssid_suffix" 'psk2+ccmp' "$random_psk" uci_commit wireless } # Delete all managed VAPs and re-create them according to the current # configuration. # # Unlike the above, this is destructive in that all VAPs not marked as # repacd_security_unmanaged will be deleted. If this is not desired, set the # FirstConfigRequired flag to 0 to prevent this step from taking place. In # this case, the VAPs must be created manually in a manner that matches the # expectations of this script. # # input: $1 - is_controller: whether this device is acting as the controller __repacd_reset_map_default_config() { local is_controller=$1 local fronthaul_ssid fronthaul_key backhaul_ssid backhaul_key local backhaul_suffix config_load repacd config_get fronthaul_ssid MAPConfig 'FronthaulSSID' '' config_get fronthaul_key MAPConfig 'FronthaulKey' '' config_get backhaul_ssid MAPConfig 'BackhaulSSID' '' config_get backhaul_key MAPConfig 'BackhaulKey' '' config_get backhaul_suffix MAPConfig 'BackhaulSuffix' '' config_load wireless config_foreach __repacd_delete_managed_vaps wifi-iface $managed_network uci_commit wireless # Clear out the environment of all CONFIG_ variables. Seems like there # should be some way to do this in UCI. unset $(set | grep '^CONFIG_' | awk -F'=' '{print $1}') # Reload to reset our variable state after the deletion config_load wireless if [ -z "$fronthaul_ssid" ]; then local ssid_suffix __repacd_generate_ssid_suffix ssid_suffix fronthaul_ssid="mapsig-${ssid_suffix}" __repacd_generate_psk fronthaul_key fi if [ -z "$backhaul_ssid" ]; then backhaul_ssid="${fronthaul_ssid}${backhaul_suffix}" if [ "$fronthaul_ssid" = "$backhaul_ssid" ]; then backhaul_key=$fronthaul_key else __repacd_generate_psk backhaul_key fi fi __repacd_create_vaps_map "$is_controller" "$fronthaul_ssid" "$fronthaul_key" \ "$backhaul_ssid" "$backhaul_key" } # Delete all of the VAPs for the given network that are marked as unmanaged. # # input: $1 config: section being considered # input: $2 network: managed network name __repacd_delete_managed_vaps() { local config="$1" local network repacd_security_unmanaged config_get network "$config" network config_get_bool repacd_security_unmanaged "$config" repacd_security_unmanaged '0' if [ "$2" = "$network" ] && [ "$repacd_security_unmanaged" -eq 0 ]; then uci delete "wireless.$config" fi } # Create the VAPs needed for Multi-AP SIG Topology Optimization with them all # initially disabled. # # input: $1 is_controller: whether this device is acting as the controller # input: $2 fronthaul_ssid: the SSID to use on all fronthaul VAPs # input: $3 fronthaul_key: the PSK for the fronthaul, or the empty string # for open mode # input: $4 backhaul_ssid: the SSID to use on all backhaul VAPs # input: $5 backhaul_key: the PSK for the backhaul, or the empty string # for open mode __repacd_create_vaps_map() { local is_controller=$1 local fronthaul_ssid=$2 local fronthaul_key=$3 local backhaul_ssid=$4 local backhaul_key=$5 local fronthaul_encryption backhaul_encryption # Whether the same VAP is used for fronthaul and backhaul or not. local shared_vaps=0 if [ "$fronthaul_ssid" = "$backhaul_ssid" ]; then shared_vaps=1 fi if [ -n "$fronthaul_key" ]; then fronthaul_encryption='psk2+ccmp' fi if [ -n "$backhaul_key" ]; then backhaul_encryption='psk2+ccmp' else backhaul_encryption='none' fi local DEVICES= __repacd_get_devices DEVICES for device in $DEVICES; do local repacd_auto_create_vaps repacd_create_bsta repacd_bsta_pref local create_ctrl_fbss create_ctrl_bbss config_get_bool repacd_auto_create_vaps "$device" repacd_auto_create_vaps '1' config_get_bool repacd_create_bsta "$device" repacd_create_bsta '1' config_get repacd_bsta_pref "$device" repacd_map_bsta_preference '0' config_get_bool create_ctrl_fbss "$device" repacd_create_ctrl_fbss '1' config_get_bool create_ctrl_bbss "$device" repacd_create_ctrl_bbss '1' uci_set wireless $device disabled '0' if [ "$repacd_auto_create_vaps" -gt 0 ] && [ "$repacd_create_bsta" -gt 0 ] && \ ! whc_is_5g_radio "$device"; then # Create a bSTA interface name=$(uci add wireless wifi-iface) config_changed=1 __repacd_init_vap "$name" $device 'sta' "$backhaul_ssid" \ $backhaul_encryption "$backhaul_key" __repacd_update_vap_param "$name" 'map' 1 __repacd_update_vap_param "$name" 'MapBSSType' 128 __repacd_update_vap_param "$name" 'wps_state' 1 __repacd_update_vap_param "$name" 'wps_pbc_skip_connected_sta' 1 # For initial onboarding, 2.4 GHz is the selected bSTA radio # (unless it is given a preference value of 0, in which case # no radio is marked as selected and we let the preference values # determine it entirely). if whc_is_5g_vap "$name" || [ "$repacd_bsta_pref" -eq 0 ]; then uci_set wireless $device repacd_map_bsta_selected '0' else uci_set wireless $device repacd_map_bsta_selected '1' fi fi # If not acting as the controller, we will let the Multi-AP # Configuration procedure create the BSSes. However, due to # limitations in wsplcd, we have to create a BSS on each radio to # ensure AP Auto-Config takes place. If this is removed, then repacd # can be updated to only do this on the controller again. if [ "$repacd_auto_create_vaps" -gt 0 ]; then # Only create the fBSS on agents (to ensure wsplcd works) or on # the controller if so configured. if [ "$is_controller" -eq 0 ] || [ "$create_ctrl_fbss" -gt 0 ]; then # Create the fBSS (which may also be a bBSS) name=$(uci add wireless wifi-iface) config_changed=1 __repacd_init_vap "$name" $device 'ap' "$fronthaul_ssid" \ $fronthaul_encryption "$fronthaul_key" __repacd_update_vap_param "$name" 'map' 1 if [ "$shared_vaps" -gt 0 ]; then # fBSS uses same VAP as bBSS __repacd_update_vap_param "$name" 'MapBSSType' 96 __repacd_update_vap_param "$name" 'multi_cred' 0 else # Distinct VAPs for backhaul and fronthaul __repacd_update_vap_param "$name" 'MapBSSType' 32 __repacd_update_vap_param "$name" 'multi_cred' 1 fi fi # Now create the bBSS, but only on the controller if configured (and # only if it is meant to be a unique BSS). The agent will have any # bBSSes created via the AP Auto-Configuration process. if [ "$is_controller" -gt 0 ] && [ "$create_ctrl_bbss" -gt 0 ] && \ [ "$shared_vaps" -eq 0 ]; then name=$(uci add wireless wifi-iface) config_changed=1 __repacd_init_vap "$name" $device 'ap' "$backhaul_ssid" \ $backhaul_encryption "$backhaul_key" __repacd_update_vap_param "$name" 'map' 1 __repacd_update_vap_param "$name" 'MapBSSType' 64 # Need to force this disabled per the Multi-AP SIG spec __repacd_update_vap_param "$name" 'wps_pbc' 0 fi fi done uci_commit wireless } # Enumerate all of the devices and append them to the variable provided. # input: $1 devices: variable to populate with the devices __repacd_get_devices() { local devices=$1 config_cb() { local type="$1" local section="$2" case "$type" in wifi-device) config_get hwmode "$section" hwmode config_get type "$section" type if [ "$type" != 'mac80211' ] && [ "$hwmode" != '11ad' ];then eval append $devices "$section" fi ;; esac } config_load wireless } # Enable all Wi-Fi devices __repacd_enable_wifi() { local DEVICES= local device changed=0 __repacd_get_devices DEVICES for device in $DEVICES; do config_get_bool disabled $device disabled [ -z "$disabled" ] && continue [ "$disabled" -eq 0 ] && continue uci_set wireless $device disabled '0' changed=1 done if [ "$changed" -gt 0 ]; then uci_commit wireless config_changed=1 fi } # Set the parameter in the wireless configuration section provided, recording # if it actually needed to be changed. # input: $1 iface_name: section name # input: $2 param_name: the name of the parameter being set # input: $3 param_val: the new value for the parameter __repacd_update_vap_param() { local iface_name=$1 param_name=$2 param_val=$3 local cur_val config_get cur_val "$iface_name" "$param_name" if [ -z "$cur_val" ] || [ ! "$cur_val" = "$param_val" ]; then uci_set wireless "$iface_name" "$param_name" "$param_val" config_changed=1 fi } # Determine the SSID to apply to a specific VAP based on the current # configuration of the WPS Push Button Configuration enhancement. # input: $1 name: section name # input: $2 device: name of the radio # input: $3 base_ssid: the SSID from which to derive other ones __repacd_init_vap_set_ssid_and_pbc() { local name=$1 device=$2 base_ssid=$3 local mode local enable_wps_re_enhc global_suffix='' radio_suffix='' local start_time duration local auto_create_vaps # Grab the overall enable first config_get enable_wps_re_enhc qcawifi wps_pbc_extender_enhance '0' # Now VAP specific parameters config_get mode "$name" mode config_get start_time "$name" wps_pbc_start_time config_get duration "$name" wps_pbc_duration config_get_bool repacd_security_unmanaged "$name" repacd_security_unmanaged '0' config_get_bool auto_create_vaps "$device" repacd_auto_create_vaps '1' if [ "$enable_wps_re_enhc" -gt 0 ]; then # Only apply the SSID derivation rules on AP interfaces. if __repacd_is_matching_mode 'ap' $mode; then # Potentially two suffixes can be applied # First is set at the overall AP level. config_get global_suffix qcawifi wps_pbc_overwrite_ssid_suffix '' # Second is set at the radio level config_get radio_suffix "$device" wps_pbc_overwrite_ssid_band_suffix '' fi fi if [ "$repacd_security_unmanaged" -eq 0 ] ; then __repacd_update_vap_param "$name" 'ssid' "$base_ssid$global_suffix$radio_suffix" fi __repacd_update_vap_param "$name" 'wps_pbc' 1 __repacd_update_vap_param "$name" 'wps_pbc_enable' "$enable_wps_re_enhc" if [ "$traffic_separation_enabled" -gt 0 ]; then __repacd_update_vap_param "$name" 'wps_pbc_noclone' '1' fi # Without a custom config, set all interfaces to be enabled for 2 minutes. if [ -z "$start_time" ]; then __repacd_update_vap_param "$name" 'wps_pbc_start_time' 0 fi if [ -z "$duration" ]; then if [ "$traffic_separation_enabled" -gt 0 ] && [ "$auto_create_vaps" -eq 1 ]; then __repacd_update_vap_param "$name" 'wps_pbc_duration' 60 else __repacd_update_vap_param "$name" 'wps_pbc_duration' 120 fi fi } # Set all of the configuration parameters for the given VAP. # input: $1 name: section name # input: $2 device: name of the radio # input: $3 mode: whether to act as a STA or AP # input: $4 ssid: the desired SSID for this VAP # input: $5 encryption: the desired encryption mode for this VAP # input: $6 key: the desired passphrase for this VAP __repacd_init_vap() { local name=$1 device=$2 mode=$3 ssid=$4 encryption=$5 key=$6 local cur_mode config_get_bool repacd_security_unmanaged "$name" repacd_security_unmanaged '0' __repacd_update_vap_param "$name" 'device' "$device" __repacd_update_vap_param "$name" 'network' $managed_network __repacd_init_vap_set_ssid_and_pbc "$name" "$device" "$ssid" if [ "$repacd_security_unmanaged" -eq 0 ] ; then __repacd_update_vap_param "$name" 'encryption' "$encryption" __repacd_update_vap_param "$name" 'key' "$key" fi # Mode needs to be handled separately. If the device is already in one # of the AP modes and the init is requesting an AP mode, we leave it as # is. If it is already in the STA mode, we also leave it as is. config_get cur_mode "$name" 'mode' if ! __repacd_is_matching_mode "$mode" "$cur_mode"; then uci_set wireless "$name" 'mode' "$mode" config_changed=1 fi } # Initialise all the additional that we created to support multi ssid traffic # separation. # input: $1 name: section name # input: $2 device: name of the radio # input: $3 mode: whether to act as a STA or AP # input: $4 hwmode: radio hardware mode # input: $5 network: desired network for this VAP # input: $6 ssid: the desired SSID for this VAP # input: $7 encryption: the desired encryption mode for this VAP # input: $8 key: the desired passphrase for this VAP __repacd_init_additional_vap() { local name=$1 device=$2 mode=$3 hwmode=$4 network=$5 local ssid=$6 encryption=$7 key=$8 local cur_mode repacd_security_unmanaged auto_create_vaps local enable_wds enable_rrm enable_qwrap_ap enable_extap block_dfs local rate_scaling_factor=0 local num_changes=0 local cur_key __repacd_update_vap_param "$name" 'device' "$device" __repacd_update_vap_param "$name" 'network' "$network" config_get_bool repacd_security_unmanaged "$name" repacd_security_unmanaged '0' if [ "$repacd_security_unmanaged" -eq 0 ] ; then __repacd_update_vap_param "$name" 'ssid' "$ssid" __repacd_update_vap_param "$name" 'encryption' "$encryption" config_get cur_key "$name" 'key' if [ ! "$cur_key" = "$key" ]; then __repacd_update_vap_param "$name" 'key' "$key" fi fi # using SON mode related settings to config backhaul VAPs. config_get_bool auto_create_vaps "$device" repacd_auto_create_vaps '1' if [ "$network" = "$network_backhaul" ] && [ "$auto_create_vaps" -eq 1 ]; then __repacd_update_vap_param "$name" 'wps_pbc_noclone' '0' __repacd_update_vap_param "$name" 'wps_pbc_enable' '1' __repacd_update_vap_param "$name" 'wps_pbc' '1' __repacd_update_vap_param "$name" 'wps_pbc_start_time' '61' __repacd_update_vap_param "$name" 'wps_pbc_duration' '120' __repacd_update_vap_param "$name" 'wds' '1' __repacd_update_vap_param "$name" 'extap' '0' if __repacd_is_matching_mode 'ap' "$mode"; then __repacd_update_vap_param "$name" 'qwrap_ap' '0' __repacd_update_vap_param "$name" 'rrm' '1' __repacd_update_vap_param "$name" 'hidden' '0' if __repacd_is_block_dfs; then __repacd_update_vap_param "$name" 'blockdfschan' '1' else __repacd_update_vap_param "$name" 'blockdfschan' '0' fi fi else __repacd_echo "Auto create VAPs disabled" fi if [ "$network" = "$network_guest" ] && [ "$auto_create_vaps" -eq 1 ]; then __repacd_update_vap_param "$name" 'rrm' '1' fi # This is mainly for wsplcd optimization: if wsplcd detects athnewind # is set to 0, it will not restart VAP; otherwise it will bring down # the VAP, set athnewind to 0 and bring the VAP back up __repacd_update_vap_param "$name" 'athnewind' 0 # Mode needs to be handled separately. If the device is already in one # of the AP modes and the init is requesting an AP mode, we leave it as # is. If it is already in the STA mode, we also leave it as is. config_get cur_mode "$name" 'mode' if ! __repacd_is_matching_mode "$mode" "$cur_mode"; then uci_set wireless "$name" 'mode' "$mode" config_changed=1 fi } # Create the 4 VAPs needed (1 STA and 1 AP for each radio), with them all # initially disabled. Three radio platforms are not currently handled. # # Note that if the VAPs already exist, they will be reconfigured as # appropriate. Existing VAP section names are given by ${device}_ap and # ${device}_sta global variables. # # input: $1 ssid: the SSID to use on all VAPs # input: $2 encryption: the encryption mode to use on all VAPs # input: $3 key: the pre-shared key to use on all VAPs __repacd_create_vaps() { local ssid=$1 local encryption=$2 local key=$3 local DEVICES= local backhaul_selected=0 __repacd_get_devices DEVICES for device in $DEVICES; do if whc_is_5g_radio $device && [ "$backhaul_selected" -eq 0 ]; then # 5 GHz and we do not have a backhaul interface yet, so select # this one as the backhaul interface. # # @todo Consider which 5 GHz radio should be used for backhaul if # there is more than one. backhaul_selected=1 fi config_get_bool repacd_auto_create_vaps "$device" repacd_auto_create_vaps '1' uci_set wireless $device disabled '0' local name name=$(eval "echo \$${device}_ap") if [ -z "$name" ] && [ "$repacd_auto_create_vaps" -eq 1 ]; then # No existing entry; create a new one. name=$(uci add wireless wifi-iface) config_changed=1 fi if [ -n "$name" ]; then # In case of auto config, this will be the fronthaul+backhaul AP VAP # However in manual config, this can be the fronthaul VAP # In manual cofig user sets this flag # We use repacd_auto_create_vaps to distinguish the two cases if [ "$repacd_auto_create_vaps" -eq 1 ]; then uci_set wireless "$name" backhaul_ap '1' fi __repacd_init_vap "$name" $device 'ap' "$ssid" "$encryption" "$key" fi name=$(eval "echo \$${device}_sta") if [ -z "$name" ] && [ "$repacd_auto_create_vaps" -eq 1 ] && \ [ "$traffic_separation_active" -eq 0 ]; then # No existing entry; create a new one. name=$(uci add wireless wifi-iface) config_changed=1 fi if [ -n "$name" ]; then __repacd_init_vap "$name" $device 'sta' "$ssid" "$encryption" "$key" fi done uci_commit wireless } # Create the additional vaps required for multi ssid traffic separation. # 1 guest vap and 1 spcl vap on each radio. Currently no sta vaps created. # spcl vap on 2.4GHz band will be disabled. # Note that if the VAPs already exist, they will be reconfigured as # appropriate. Existing VAP section names are given by # ${device}_(backhaul/guest)_ap and # ${device}_(backhaul/guest)_sta global variables. # # input: $1 network: network to which this vap belongs # input: $2 ssid: the SSID to use on all VAPs for the provided network # input: $3 encryption: the encryption mode to use on all VAPs # input: $4 key: the pre-shared key to use on all VAPs __repacd_create_additional_vaps() { local ssid=$2 local encryption=$3 local key=$4 local network=$1 local DEVICES= local no_vlan_val local hwmode marker if [ "$network" = "$network_backhaul" ]; then marker="backhaul" elif [ "$network" = "$network_guest" ]; then marker="guest" fi __repacd_get_devices DEVICES for device in $DEVICES; do config_get_bool repacd_auto_create_vaps "$device" repacd_auto_create_vaps '1' uci_set wireless $device disabled '0' config_get hwmode $device hwmode config_get no_vlan_val $device no_vlan '0' if [ "$no_vlan_val" -eq 0 ]; then uci_set wireless $device no_vlan '1' fi local name_managed name_managed=$(eval "echo \$${device}_ap") local name name=$(eval "echo \$${device}_${marker}_ap") if [ -z "$name" ] && [ "$repacd_auto_create_vaps" -eq 1 ]; then # No existing entry; create a new ap. name=$(uci add wireless wifi-iface) config_changed=1 fi if [ -n "$name" ]; then if [ "$network" = "$network_backhaul" ]; then uci_set wireless "$name" rept_spl '1' if [ "$repacd_auto_create_vaps" -eq 1 ]; then uci_set wireless "$name" backhaul_ap '1' fi if [ -n "$name_managed" ]; then uci_set wireless "$name"_managed backhaul_ap '0' fi fi __repacd_init_additional_vap "$name" $device 'ap' "$hwmode" "$network" \ "$ssid" "$encryption" "$key" fi if [ $create_sta -eq 1 ]; then name=$(eval "echo \$${device}_${marker}_sta") if [ -z "$name" ] && [ "$repacd_auto_create_vaps" -eq 1 ]; then # No existing entry; create a new sta. name=$(uci add wireless wifi-iface) config_changed=1 fi if [ -n "$name" ]; then __repacd_init_additional_vap "$name" $device 'sta' "$hwmode" "$network" \ "$ssid" "$encryption" "$key" fi fi done uci_commit wireless } # Reconfigure the STA vaps of managed network. # After restarting in Non CAP mode we reconfigure the sta vaps # to be part of backhaul network. Network,ssid and credential # are changed other configuration remains same. # # input: $1 config: section name # input: $2 : current network # input: $3 : backhaul network # input: $4 ssid_val: backhaul ssid # input: $5 enc_val: backhaul encryption # input: $6 key_val: backhaul key __repacd_reconfig_sta_vaps() { local config=$1 local network local ssid_val="$4" local enc_val="$5" local key_val="$6" config_get network "$config" network if [ "$2" = "$network" ] || [ "$3" = "$network" ]; then local mode device hwmode type_val disabled config_get mode "$config" mode config_get device "$config" device config_get hwmode "$device" hwmode config_get type_val "$device" type config_get disabled "$config" disabled 0 if [ "$hwmode" = '11ad' ] && [ "$type_val" = 'mac80211' ] ;then return fi if [ "$mode" = "sta" ]; then uci_set wireless "$config" rept_spl '1' __repacd_init_additional_vap "$config" $device 'sta' "$hwmode" "$3" \ "$ssid_val" "$enc_val" "$key_val" fi fi } # Determine if the mode on the interface is a match. # This does fuzzy matching in that multiple actual modes are said to match # a given general mode. # # input: $1 general_mode: one of 'sta' or 'ap' # input: $2 cur_mode: the currently configured mode # return: 0 on a match; otherwise non-zero __repacd_is_matching_mode() { local general_mode=$1 local cur_mode=$2 if [ "$general_mode" = 'sta' ]; then if [ "$cur_mode" = 'sta' ]; then return 0 else return 1 fi else if [ "$cur_mode" = 'ap' ] || [ "$cur_mode" = 'wrap' ]; then return 0 else return 1 fi fi } # Detect which VAPs are already configured and their corresponding SSID and # passphrase. # # input: $1 config: section name # input: $2 network: network for which to update VAPs # # Updates $resolved_ssid, $resolved_enc, and $resolved_key as appropriate. __repacd_resolve_vaps() { local config="$1" local network config_get network "$config" network if [ "$2" = "$network" ]; then local device mode ssid_val encryption_val key_val config_get device "$config" device config_get mode "$config" mode config_get ssid_val "$config" ssid config_get encryption_val "$config" encryption config_get key_val "$config" key config_get disabled "$config" disabled 0 config_get_bool repacd_security_unmanaged "$config" repacd_security_unmanaged '0' config_get hwmode "$device" hwmode config_get type "$device" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] ;then return fi local default_ap default_ap=$(eval "echo \$${device}_ap") # Remember the section name for this radio in this mode. if __repacd_is_matching_mode 'ap' "$mode"; then if [ -z "$default_ap" ]; then eval "${device}_ap=$config" fi elif [ "$mode" = "sta" ]; then eval "${device}_sta=$config" fi if [ "$repacd_security_unmanaged" -eq 1 ] ; then return fi # Since there is really no way to know which SSID, encryption mode, or # passphrase to use, we will only store the first one unless we come # across an enabled STA interface in which case we will prefer that. # The reason for this is because if WPS is used without wsplcd, only # the STA interface will have the correct SSID and passphrase once the # process completes. When switching from pure client mode to RE mode, # we want to propagate those values to the AP interfaces and the other # STA interface. if [ -n "$ssid_val" ] && [ -z "$resolved_ssid" ] || [ "$mode" = "sta" ]; then if [ "$disabled" -eq 0 ]; then resolved_ssid="$ssid_val" fi fi if [ -n "$encryption_val" ] && [ -z "$resolved_enc" ] || [ "$mode" = "sta" ]; then if [ "$disabled" -eq 0 ]; then resolved_enc="$encryption_val" fi fi if [ -n "$key_val" ] && [ -z "$resolved_key" ] || [ "$mode" = "sta" ]; then if [ "$disabled" -eq 0 ]; then resolved_key="$key_val" fi fi fi } # Detect which additional VAPs are already configured. # # input: $1 config: section name # input: $2 network: network for which to update VAPs __repacd_resolve_additional_vaps() { local config="$1" local network marker config_get network "$config" network if [ "$2" = "$network" ]; then local device mode hwmode type_val encryption_val key_val if [ "$network" = "$network_backhaul" ]; then marker="backhaul" elif [ "$network" = "$network_guest" ]; then marker="guest" fi config_get device "$config" device config_get mode "$config" mode config_get ssid_val "$config" ssid config_get encryption_val "$config" encryption config_get key_val "$config" key config_get disabled "$config" disabled 0 config_get hwmode "$device" hwmode config_get type_val "$device" type if [ "$hwmode" = '11ad' ] && [ "$type_val" = 'mac80211' ] ;then return fi # Remember the section name for this radio in this mode. if __repacd_is_matching_mode 'ap' "$mode"; then eval "${device}_${marker}_ap=$config" elif [ "$mode" = "sta" ]; then eval "${device}_${marker}_sta=$config" fi if [ -n "$ssid_val" ] && [ "$disabled" -eq 0 ]; then if [ "$network" = "$network_backhaul" ]; then if [ "$backhaul_ssid" = "$def_backhaul_ssid" ] || [ "$mode" = "sta" ]; then backhaul_ssid="$ssid_val" fi elif [ "$network" = "$network_guest" ]; then if [ "$guest_ssid" = "$def_guest_ssid" ]; then guest_ssid="$ssid_val" fi fi fi if [ -n "$encryption_val" ] && [ "$disabled" -eq 0 ]; then if [ "$network" = "$network_backhaul" ]; then if [ "$backhaul_enc" = "$def_backhaul_enc" ] || [ "$mode" = "sta" ]; then backhaul_enc="$encryption_val" fi elif [ "$network" = "$network_guest" ]; then if [ "$guest_enc" = "$def_guest_enc" ]; then guest_enc="$encryption_val" fi fi fi if [ -n "$key_val" ] && [ "$disabled" -eq 0 ]; then if [ "$network" = "$network_backhaul" ]; then if [ "$backhaul_key" = "$def_backhaul_key" ] || [ "$mode" = "sta" ]; then backhaul_key="$key_val" fi elif [ "$network" = "$network_guest" ]; then if [ "$guest_key" = "$def_guest_key" ]; then guest_key="$key_val" fi fi fi fi } # Configure the additional VAPs needed to be consistent with the configuration that # would be produced if starting from a default configuration. If any VAPs # need to be created, use the SSID with suitable suffix, encryption mode, and passphrase # from the managed network vaps __repacd_reset_additional_config() { config_load wireless config_foreach __repacd_resolve_additional_vaps wifi-iface $network_guest config_foreach __repacd_resolve_additional_vaps wifi-iface $network_backhaul __repacd_create_additional_vaps $network_backhaul "$backhaul_ssid" "$backhaul_enc" \ "$backhaul_key" __repacd_create_additional_vaps $network_guest "$guest_ssid" "$guest_enc" \ "$guest_key" } # Configure the 4 VAPs needed to be consistent with the configuration that # would be produced if starting from a default configuration. If any VAPs # need to be created, carry over the SSID, encryption mode, and passphrase # from one of the existing ones. __repacd_reset_existing_config() { config_load wireless config_foreach __repacd_resolve_vaps wifi-iface $managed_network __repacd_create_vaps "$resolved_ssid" "$resolved_enc" "$resolved_key" } # Set all VAPs for the given network and mode to disabled or enabled (per # the parameters). # # input: $1 config: section name # input: $2 network: network for which to update VAPs # input: $3 mode: sta or ap # input: $4 disable_24g: 1 - disable, 0 - enable # input: $5 disable_5g: 1 - disable, 0 - enable # input-output: $6 change counter __repacd_disable_vap() { local config="$1" local disable_24g="$4" local disable_5g="$5" local mode network disabled local changed="$6" config_get device "$config" device config_get hwmode "$device" hwmode config_get type "$device" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] ;then return fi config_get mode "$config" mode config_get network "$config" network config_get disabled "$config" disabled 0 if [ "$2" = "$network" ] && __repacd_is_matching_mode "$3" "$mode"; then local desired_val if whc_is_5g_vap "$config"; then desired_val=$disable_5g else desired_val=$disable_24g fi if [ ! "$desired_val" = "$disabled" ]; then uci_set wireless "$config" disabled "$desired_val" changed=$((changed + 1)) eval "$6='$changed'" __repacd_echo "Set VAP $config to Disabled=$desired_val" fi fi } # Determine the radio on which the bSTA should be allocated. # # If a radio is marked as selected (using the repacd_map_bsta_selected config # option), it will be used. If instead none is marked, the radio with the # highest repacd_map_bsta_pref value will be used. # # input: $1 config: section name # output: $2 selected_radio: the radio that is marked as selected # output: $3 preferred_radio: the radio with the highest preference __repacd_resolve_bsta_radio() { local config="$1" local bsta_selected='' bsta_preference='' config_get bsta_selected "$config" repacd_map_bsta_selected 0 config_get bsta_preference "$config" repacd_map_bsta_preference if [ "$bsta_selected" -gt 0 ]; then eval "$2=$config" fi # Radios with no preference set are ignored. This is meant to indicate # the OEM never wants to use that radio. if [ -n "$bsta_preference" ]; then if [ "$bsta_preference" -gt "$map_bsta_max_preference" ]; then eval "$3=$config" map_bsta_max_preference="$bsta_preference" fi fi } # Update the radio on which the bSTA VAP is allocated based on the setting # at the radio level. # # input: $1 config: section name # input: $2 selected_radio: name of the radio on which to run the bSTA # input: $3 network: network for which to update VAPs # input-output: $4 change counter __repacd_update_map_bsta_radio() { local config="$1" local selected_radio="$2" local changed="$4" local device hwmode type config_get device "$config" device config_get hwmode "$device" hwmode config_get type "$device" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] ;then return fi local mode network disabled bssid config_get mode "$config" mode config_get network "$config" network config_get disabled "$config" disabled 0 config_get bssid "$config" bssid if [ "$3" = "$network" ] && __repacd_is_matching_mode "sta" "$mode"; then if [ ! "$device" = "$selected_radio" ]; then uci_set wireless "$config" device "$selected_radio" changed=$((changed + 1)) eval "$4='$changed'" __repacd_echo "Set VAP $config to device=$selected_radio" if [ -n "$bssid" ]; then uci delete "wireless.${config}.bssid" __repacd_echo "Removed BSSID from VAP $config due to radio change" fi fi if [ "$disabled" -eq 1 ]; then uci_set wireless "$config" disabled 0 changed=$((changed + 1)) eval "$4='$changed'" __repacd_echo "Set VAP $config to Disabled=0" fi fi } # Delete the bssid entry from the given STA interface. # # input: $1 config: section name # input: $2 network: network being managed # output: $3 config_changed: number of configurations changed __repacd_delete_bssid_entry() { local config="$1" local network_to_match="$2" local changed="$3" local device hwmode network mode bssid config_get device "$config" device config_get hwmode "$device" hwmode config_get network "$config" network config_get type "$device" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] \ || [ "$network" != "$network_to_match" ]; then return fi config_get mode "$config" mode if __repacd_is_matching_mode 'sta' "$mode"; then config_get bssid "$config" bssid '' if [ -n "$bssid" ]; then __repacd_echo "Deleting BSSID $bssid" uci delete "wireless.${config}.bssid" changed=$((changed + 1)) eval "$3='$changed'" fi fi } # Change the wsplcd running mode based on the value provided. # # input: $1 new_mode: value to set wsplcd run mode to # input: $2 new_deep_clone: whether to enable deep cloning (which copies the # channel and locks the association to the CAP) # input: $3 new_deep_clone_no_bssid: deep cloning without BSSID cloning # input: $4 config_sta: whether to use the extension to configure a STA # interface during cloning # input: $5 map_enable: whether to operate in Multi-AP SIG mode # input-output: $6 changed: count of the changes __repacd_configure_wsplcd() { local new_mode=$1 local new_deep_clone=$2 local new_deep_clone_no_bssid=$3 local new_config_sta=$4 local new_map_enable=$5 local changed="$6" local mode deep_clone deep_clone_no_bssid manage_vapind enabled local map_bss_conf if [ -f $WSPLCD_INIT ]; then config_load wsplcd config_get mode config 'RunMode' config_get deep_clone config 'DeepClone' config_get deep_clone_no_bssid config 'DeepCloneNoBSSID' config_get config_sta config 'ConfigSta' config_get map_enable config 'MapEnable' config_get map_bss_conf config 'MapGenericPolicyFile' config_get manage_vapind config 'ManageVAPInd' config_get_bool enabled config 'HyFiSecurity' 0 if [ ! "$mode" = "$new_mode" ]; then uci_set wsplcd config 'RunMode' "$new_mode" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd to $new_mode mode" wsplcd_restart=1 fi if [ ! "$deep_clone" = "$new_deep_clone" ]; then uci_set wsplcd config 'DeepClone' "$new_deep_clone" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd DeepClone=$new_deep_clone" wsplcd_restart=1 fi if [ ! "$deep_clone_no_bssid" = "$new_deep_clone_no_bssid" ]; then uci_set wsplcd config 'DeepCloneNoBSSID' "$new_deep_clone_no_bssid" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd DeepCloneNoBSSID=$new_deep_clone_no_bssid" wsplcd_restart=1 fi if [ ! "$config_sta" = "$new_config_sta" ]; then uci_set wsplcd config 'ConfigSta' "$new_config_sta" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd ConfigSta=$new_config_sta" wsplcd_restart=1 fi if [ ! "$map_enable" = "$new_map_enable" ]; then uci_set wsplcd config 'MapEnable' "$new_map_enable" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd MapEnable=$new_map_enable" wsplcd_restart=1 fi if [ "$new_map_enable" -gt 0 ] && \ [ ! "$map_bss_conf" = "$WSPLCD_MAP_BSS_POLICY_PATH" ]; then uci_set wsplcd config 'MapGenericPolicyFile' "$WSPLCD_MAP_BSS_POLICY_PATH" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd MapGenericPolicyFile=$WSPLCD_MAP_BSS_POLICY_PATH" wsplcd_restart=1 fi if [ ! "$manage_vapind" = "0" ]; then uci_set wsplcd config 'ManageVAPInd' "0" changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd ManageVAPInd=0" wsplcd_restart=1 fi if [ ! "$enabled" -eq "$wsplcd_enabled" ]; then uci_set wsplcd config 'HyFiSecurity' $wsplcd_enabled changed=$((changed + 1)) eval "$6='$changed'" uci_commit wsplcd __repacd_echo "Set wsplcd HyFiSecurity=$wsplcd_enabled" if [ "$wsplcd_enabled" -gt 0 ]; then __repacd_echo "Enabled security and configuration" wsplcd_start=1 else __repacd_echo "Disabled security and configuration" wsplcd_stop=1 fi fi fi } # Change whether mcsd is enabled and running or not # # input: $1 manage_mcsd: whether repacd is to manage the state of mcsd # input: $2 enable_son: whether SON mode is enabled or not (where this could # include MAP) __repacd_config_mcsd() { local manage_mcsd=$1 local enable_son=$2 if [ "$manage_mcsd" -gt 0 ] && [ -f "$MCSD_INIT" ]; then if [ "$enable_son" -gt 0 ]; then uci_set mcsd config 'Enable' 0 uci_commit mcsd # Stop mcsd and keep attempting to stop it in case it # is being restarted by a hotplug event. while pgrep mcsd; do /etc/init.d/mcsd stop sleep 2 done else # switching to non-SON mode, so enable mcsd uci_set mcsd config 'Enable' 1 uci_commit mcsd /etc/init.d/mcsd start fi fi } # Change the hyd and/or lbd configuration based on the parameters provided # and the allowed feature settings. # # input: $1 enable_steering: 1 - AP interfaces support steering; # 0 - they do not # input: $2 disable_ap_steering: 1 - disable AP steering feature # input: $3 enable_son: 1 - multi-AP SON mode should be enabled (so # long as it is not prohibited by config); # 0 - multi-AP SON mode should not be enabled # input: $4 son_mode: one of HYROUTER or HYCLIENT; only relevant if enable_son # is 1 and SON mode is not prohibited by the config # input-output: $5 changed: count of the changes __repacd_configure_son() { local enable_steering=$1 local disable_ap_steering=$2 local enable_son=$3 local son_mode="$4" local changed="$5" local enable_steering_mask enable_son_mask manage_mcsd config_load repacd config_get_bool enable_steering_mask repacd 'EnableSteering' 1 config_get_bool enable_son_mask repacd 'EnableSON' 1 config_get_bool manage_mcsd repacd 'ManageMCSD' 1 # If the config does not permit steering or multi AP logic, force it # off. if [ "$enable_steering_mask" -eq 0 ]; then enable_steering=0 fi if [ "$enable_son_mask" -eq 0 ]; then enable_son=0 fi # If the package is not even installed, then we will fall back to # the uncoordinated steering mode (if enabled). if [ -f $HYD_INIT ]; then local cur_mode hyd_enabled config_load hyd config_get cur_mode config 'Mode' config_get hyd_enabled config 'Enable' config_get disable_steering config 'DisableSteering' if [ ! "$cur_mode" = "$son_mode" ]; then uci_set hyd config 'Mode' "$son_mode" changed=$((changed + 1)) eval "$5='$changed'" uci_commit hyd __repacd_echo "Set hyd Mode=$son_mode" fi if [ ! "$disable_steering" = "$disable_ap_steering" ]; then uci_set hyd config 'DisableSteering' "$disable_ap_steering" changed=$((changed + 1)) eval "$5='$changed'" uci_commit hyd __repacd_echo "Set hyd DisableSteering=$disable_ap_steering" fi if [ ! "$hyd_enabled" = "$enable_son" ]; then uci_set hyd config 'Enable' "$enable_son" changed=$((changed + 1)) eval "$5='$changed'" uci_commit hyd /etc/init.d/qrfs disable /etc/init.d/qrfs stop __repacd_config_mcsd "$manage_mcsd" "$enable_son" # hyd should be started/stopped based on the hotplug hooks # it has installed. if [ "$enable_son" -gt 0 ]; then __repacd_echo "Enabled Wi-Fi SON mode" hyd_start=1 else __repacd_echo "Disabled Wi-Fi SON mode" hyd_stop=1 fi fi if [ "$enable_son" -gt 0 ]; then enable_steering=0 fi fi if [ -f $LBD_INIT ]; then local lbd_enabled config_load lbd config_get lbd_enabled config 'Enable' if [ ! "$lbd_enabled" = "$enable_steering" ]; then uci_set lbd config 'Enable' "$enable_steering" changed=$((changed + 1)) eval "$5='$changed'" uci_commit lbd # Start/stop is handled when Wi-Fi interfaces are reconfigured. if [ "$enable_steering" -gt 0 ]; then __repacd_echo "Enabled Wi-Fi steering" else __repacd_echo "Disabled Wi-Fi steering" fi fi fi } # Change the configuration on the wifi-device object to match what is desired # (either QWrap enabled or disabled based on the second argument). # # input: $1 config: section to update # input: $2 1 - enable, 0 - disable # input-output: $3 change counter __repacd_config_qwrap_device() { local config="$1" local mode network local changed="$3" # @todo This will need to be updated for 3 radio configurations. The # qwrap_enable should be set for the radio with the backhaul and # qwrap_dbdc_enable should be set for the radios with only an AP # interface. config_get hwmode "$config" hwmode config_get type "$config" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ]; then return fi if whc_is_5g_radio "$1"; then local qwrap_enable config_get qwrap_enable "$config" qwrap_enable if [ ! "$2" = "$qwrap_enable" ]; then uci_set wireless "$config" qwrap_enable "$2" changed=$((changed + 1)) eval "$3='$changed'" __repacd_echo "Set radio $config to QWrap Enabled=$2" fi else # must be 2.4 GHz local qwrap_dbdc_enable config_get qwrap_dbdc_enable "$config" qwrap_dbdc_enable if [ ! "$2" = "$qwrap_dbdc_enable" ]; then uci_set wireless "$config" qwrap_dbdc_enable "$2" changed=$((changed + 1)) eval "$3='$changed'" __repacd_echo "Set radio $config to QWrap DBDC Enabled=$2" fi fi } # Set the option that indicates whether the DBDC repeater feature should be # enabled or not. # # input: $1 config: section to update # input: $2 1 - enable, 0 - disable # input-output: $3 change counter __repacd_config_dbdc_device() { local config="$1" local changed="$3" local dbdc_enable config_get hwmode "$config" hwmode config_get type "$config" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ]; then return fi config_get dbdc_enable "$config" dbdc_enable 1 if [ ! "$2" = "$dbdc_enable" ]; then uci_set wireless "$config" dbdc_enable "$2" changed=$((changed + 1)) eval "$3='$changed'" __repacd_echo "Set radio $config to DBDC Enabled=$2" fi } # Enable or disable the WPS Push Button Configuration Range Extender # enhancement based on the current configuration. # input: $1 force_cap_mode - whether to act as gateway connected even without # a WAN interface # input-output: $2 change count __repacd_config_wps_pbc_enhc() { local force_gwcon_mode=$1 local changed="$2" local cur_enable if __repacd_gw_mode || [ "$force_gwcon_mode" -gt 0 ] || \ __repacd_is_wds_mode || __repacd_is_son_mode; then if [ "$traffic_separation_enabled" -gt 0 ]; then enable_wps_pbc_enhc=1 else enable_wps_pbc_enhc=0 fi else # Must be QWRAP or ExtAP mode, where we want distinct SSIDs for the # RE interfaces. enable_wps_pbc_enhc=1 fi config_load wireless config_get cur_enable qcawifi wps_pbc_extender_enhance '0' if [ ! "$enable_wps_pbc_enhc" = "$cur_enable" ]; then # Create the section if it does not exist. uci set wireless.qcawifi=qcawifi uci_set wireless qcawifi wps_pbc_extender_enhance $enable_wps_pbc_enhc uci_set wireless qcawifi wps_pbc_overwrite_ap_settings_all 1 __repacd_echo "Set qcawifi.wps_pbc_extender_enhance=$enable_wps_pbc_enhc" __repacd_echo "Set qcawifi.wps_pbc_overwrite_ap_settings_all=1" changed=$((changed + 1)) eval "$2='$changed'" fi } # Change the configuration on the wifi-iface object to match what is desired. # The values provided are determined by the caller based on the desired # mode of operation (eg. QWrap/ExtAP or not). # # input: $1 config: section to update # input: $2 network: only update if network matches this value # input: $3 enable_wds: 1 - enable, 0 - disable # input: $4 qwrap_ap: 1 - enable, 0 - disable # input: $5 extap: 1 - enable, 0 disable # input: $6 block_dfs_chan: 1 - block DFS channels, 0 - do not block them # input: $7 enable_rrm: 1 - enable, 0 disable # input: $8 re_scalingfactor: 0 - ignore, 1 to 100 valid for sta # input: $9 default_root_dist: 0 - ignore, 255 - invalid root distance # input: $10 cap_snr: 0 - disabled, 1-100 valid # input-output: $11 change counter __repacd_config_iface() { local config="$1" local device mode network enable_wds qwrap_ap extap block_dfs enable_rrm local re_scalingfactor root_distance cap_snr wps_pbc_skip_connected_sta local bssid="00:00:00:00:00:00" local num_changes=0 local changed="${11}" config_get device "$config" device config_get hwmode "$device" hwmode config_get type "$device" type if [ "$hwmode" = '11ad' ] && [ "$type" = 'mac80211' ] ;then return fi config_get mode "$config" mode config_get network "$config" network config_get enable_wds "$config" wds '0' config_get qwrap_ap "$config" qwrap_ap '0' config_get extap "$config" extap '0' config_get block_dfs "$config" blockdfschan '0' config_get enable_rrm "$config" rrm '0' config_get re_scalingfactor "$config" re_scalingfactor '0' config_get root_distance "$config" root_distance '0' config_get cap_snr "$config" caprssi '0' config_get wps_pbc_skip_connected_sta "$config" wps_pbc_skip_connected_sta '0' if [ "$2" = "$network" ]; then if [ ! "$3" = "$enable_wds" ]; then uci_set wireless "$config" wds "$3" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to WDS=$3" fi # When operating in WDS/SON mode (since we do not use the repeater # enhancement), set the option to skip activating WPS PBC on a # connected STA interface. This allows the WPS button to be pressed on # an RE without causing it to disconnect from its upstream device. if [ "$mode" = 'sta' ]; then if [ ! "$3" = "$wps_pbc_skip_connected_sta" ]; then uci_set wireless "$config" wps_pbc_skip_connected_sta "$3" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to wps_pbc_skip_connected_sta=$3" fi fi # These should only be set on AP interfaces. if __repacd_is_matching_mode 'ap' "$mode"; then if [ ! "$4" = "$qwrap_ap" ]; then uci_set wireless "$config" qwrap_ap "$4" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to QWrapAP=$4" fi # @todo If there are multiple 5 GHz radios, will need to figure # out which can act as the backhaul. # Set the interface into wrap or vanilla AP mode as appropriate if whc_is_5g_radio $device; then if [ "$4" -gt 0 ]; then if [ ! "$mode" = 'wrap' ]; then uci_set wireless "$config" mode 'wrap' num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config mode to wrap" fi else # WDS or ExtAP mode if [ ! "$mode" = 'ap' ]; then uci_set wireless "$config" mode 'ap' num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config mode to ap" fi fi fi if [ ! "$6" = "$block_dfs" ]; then uci_set wireless "$config" blockdfschan "$6" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to BlockDFSChan=$6" fi if [ ! "$7" = "$enable_rrm" ]; then uci_set wireless "$config" rrm "$7" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to RRM=$7" fi fi if [ ! "$5" = "$extap" ]; then uci_set wireless "$config" extap "$5" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to ExtAP=$5" fi if [ "$daisy_chain" -gt 0 ] && \ __repacd_is_matching_mode 'sta' "$mode"; then # Need to resolve 2.4G BSSID, So until then configure invalid BSSID # to avoid association on 2.4G interface. # Check if bssid updated by wifimon/daisychain, needs restart if [ "$bssid_resolve_state" = "resolving" ] \ && ! whc_is_5g_radio $device; then uci_set wireless "$config" bssid "$bssid" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to BSSID=$bssid" fi if [ ! "$8" = "$re_scalingfactor" ]; then uci_set wireless "$config" re_scalingfactor "$8" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to RE_ScalingFactor=$8" fi if [ ! "${10}" = "$cap_snr" ]; then uci_set wireless "$config" caprssi "${10}" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to caprssi=${10}" fi fi if [ ! "$9" = "$root_distance" ]; then uci_set wireless "$config" root_distance "$9" num_changes=$((num_changes + 1)) __repacd_echo "Set iface $config to RootDistance=$9" fi if [ "$num_changes" -gt 0 ]; then changed=$((changed + 1)) eval "${11}='$changed'" fi fi } # Switch the device into acting as the CAP (main gateway). # Also update the range extension mode as necessary. # # input: $1 is_cap: whether the device should act as the central # AP or a secondary gateway connected AP __repacd_config_gwcon_ap_mode() { local is_cap=$1 local wsplcd_mode son_mode local rate_scaling_factor=0 local default_root_dist=0 # The WDS, VAP independent, and QWrap AP settings also need to be updated # based on the range extension mode. local enable_wds enable_rrm enable_qwrap_ap enable_extap local block_dfs enable_multi_ap disable_steering=0 config_sta=1 local map_enable=0 __repacd_get_config_re_mode config_re_mode __repacd_get_re_mode resolved_re_mode if __repacd_is_auto_re_mode $config_re_mode || __repacd_is_wds_mode || \ __repacd_is_son_mode; then if __repacd_is_auto_re_mode $config_re_mode || \ __repacd_is_son_mode; then __repacd_echo "Using SON mode for GW Connected AP" enable_multi_ap=1 else # Must be vanilla WDS __repacd_echo "Using WDS mode for GW Connected AP" enable_multi_ap=0 fi enable_wds=1 enable_rrm=1 enable_qwrap_ap=0 enable_extap=0 # In WDS/SON modes, we let the OEM customize whether DFS channels # should be permitted. if __repacd_is_block_dfs; then block_dfs=1 else block_dfs=0 fi wsplcd_enabled=1 else __repacd_echo "Using Non-WDS mode for GW Connected AP" enable_wds=0 enable_multi_ap=0 enable_rrm=0 enable_qwrap_ap=0 enable_extap=0 # In QWrap/ExtAP mode, DFS channels should always be disallowed (as it # does not appear to suppor them currently). This may be able to # relaxed in the future. block_dfs=1 # Since QWrap/ExtAP mode on the CAP is for mimicking a non-QCA AP, do # not run an IEEE P1905.1 registrar. wsplcd_enabled=0 fi config_load repacd config_get bssid_resolve_state WiFiLink 'BSSIDResolveState' 'resolving' # In GW-connected AP mode, only the AP interfaces are enabled. local disable_24g_sta=1 disable_5g_sta=1 disable_24g_ap=0 disable_5g_ap=0 config_load wireless config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'sta' $disable_24g_sta $disable_5g_sta config_changed config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'ap' $disable_24g_ap $disable_5g_ap config_changed # The QWrap parameters should always be set to 0 on the CAP. config_foreach __repacd_config_qwrap_device wifi-device \ 0 config_changed # Similarly, the DBDC repeater feature should be disabled on the # CAP. config_foreach __repacd_config_dbdc_device wifi-device \ 0 config_changed # Now set up the interfaces in the right way. config_foreach __repacd_config_iface wifi-iface \ $managed_network $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed if [ "$traffic_separation_active" -gt 0 ]; then config_foreach __repacd_config_iface wifi-iface \ $network_backhaul $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed config_foreach __repacd_config_iface wifi-iface \ $network_guest $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed fi uci_commit wireless uci_set repacd repacd Role 'CAP' uci_commit repacd if [ "$is_cap" -gt 0 ]; then wsplcd_mode='REGISTRAR' son_mode='HYROUTER' else wsplcd_mode='ENROLLEE' son_mode='HYCLIENT' fi # Deep cloning is not relevant in registrar mode, but we set it to 1 # anyways (since that is the default). __repacd_configure_wsplcd $wsplcd_mode 1 0 $config_sta $map_enable \ config_changed __repacd_configure_son $enable_wds $disable_steering $enable_multi_ap \ $son_mode config_changed } # Switch the device to act in one of the NonCAP configurations. # input: $1 disable_ap - whether to disable the AP interfaces # input: $2 deep_clone - whether to use deep cloning in wsplcd # input: $3 deep_clone_no_bssid - whether to use deep cloning without BSSID cloning in wsplcd __repacd_config_noncap_mode() { local disable_ap=$1 local deep_clone=$2 local deep_clone_no_bssid=$3 # The WDS and QWrap AP settings also need to be updated based on the # range extension mode. local enable_wds enable_qwrap_ap enable_extap enable_dbdc_repeater local block_dfs enable_rrm enable_multi_ap disable_steering=0 config_sta=1 local map_enable=0 local rate_scaling_factor=$RE_DEFAULT_RATE_ESTIMATE_SCALING_FACTOR local default_root_dist=$RE_ROOT_AP_DISTANCE_INVALID local disable_24g_sta=1 disable_5g_sta=0 local disable_24g_ap=$disable_ap disable_5g_ap=$disable_ap if __repacd_is_wds_mode || __repacd_is_son_mode; then if __repacd_is_wds_mode; then __repacd_echo "Using WDS mode for NonCAP" else # Must be SON mode __repacd_echo "Using SON mode for NonCAP" fi enable_wds=1 enable_qwrap_ap=0 enable_extap=0 # Even if we are not operating in fully coordinated steering mode, # we should enable RRM for use in the uncoordinated steering # environment. enable_rrm=1 # In WDS mode, we let the OEM customize whether DFS channels should # be permitted. if __repacd_is_block_dfs; then block_dfs=1 else block_dfs=0 fi wsplcd_enabled=1 __repacd_get_rate_scaling_factor rate_scaling_factor config_get capsnr WiFiLink 'PreferCAPSNRThreshold5G' '0' else enable_wds=0 # Until steering can be well supported on QWRAP/ExtAP, there is no real # need to have RRM enabled. enable_rrm=0 # wsplcd needs WDS in order to work (as it sends/receives using the # bridge interface MAC address). Plus, it is not too likely that the # main AP will be running an IEEE P1905.1 registrar. wsplcd_enabled=0 if [ "$disable_ap" -eq 0 ]; then if __repacd_is_qwrap_mode; then __repacd_echo "Using QWrap mode for NonCAP" enable_qwrap_ap=1 enable_extap=0 else __repacd_echo "Using ExtAP mode for NonCAP" enable_qwrap_ap=0 enable_extap=1 fi # In QWrap/ExtAP mode, DFS channels should always be disallowed # (as these modes may not support them properly). block_dfs=1 else # client mode if __repacd_is_qwrap_mode; then __repacd_echo "Using QWrap mode for NonCAP" enable_qwrap_ap=0 enable_extap=0 # @todo What mode should be used here? The STA interface is not # even created if it is not in QWRAP or WDS. We could # potentially consider standalone Proxy STA # mode, but we need details on how to configure this. else __repacd_echo "Using ExtAP mode for NonCAP" enable_qwrap_ap=0 enable_extap=1 fi # We'll rely on the main AP to decide on DFS or not. block_dfs=0 fi fi if __repacd_is_son_mode; then disable_24g_sta=0 enable_dbdc_repeater=0 enable_multi_ap=1 else enable_multi_ap=0 # Although currently in non-SON mode we do not enable both STA # interfaces, just in case we do in the future, set this flag. It # should make no difference if only one STA interface is active. enable_dbdc_repeater=1 fi config_load repacd config_get bssid_resolve_state WiFiLink 'BSSIDResolveState' 'resolving' config_load wireless if [ "$traffic_separation_active" -gt 0 ]; then config_foreach __repacd_disable_vap wifi-iface \ $network_backhaul 'sta' $disable_24g_sta $disable_5g_sta config_changed else config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'sta' $disable_24g_sta $disable_5g_sta config_changed fi config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'ap' "$disable_24g_ap" "$disable_5g_ap" config_changed # First set the special options for QWRAP and DBDC repeaters. config_foreach __repacd_config_qwrap_device \ wifi-device $enable_qwrap_ap config_changed config_foreach __repacd_config_dbdc_device wifi-device \ $enable_dbdc_repeater config_changed config_foreach __repacd_config_iface wifi-iface \ $managed_network $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed if [ "$traffic_separation_active" -gt 0 ]; then config_foreach __repacd_config_iface wifi-iface \ $network_backhaul $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed config_foreach __repacd_config_iface wifi-iface \ $network_guest $enable_wds $enable_qwrap_ap $enable_extap \ $block_dfs $enable_rrm $rate_scaling_factor $default_root_dist $capsnr config_changed fi __repacd_config_independent_vaps uci_commit wireless uci_set repacd repacd Role 'NonCAP' uci_commit repacd __repacd_configure_wsplcd 'ENROLLEE' "$deep_clone" "$deep_clone_no_bssid" \ $config_sta $map_enable config_changed __repacd_configure_son $enable_wds $disable_steering $enable_multi_ap \ 'HYCLIENT' config_changed } # Switch the device into acting as a range extender. # Also update the range extension mode as necessary. __repacd_config_re_mode() { local disable_ap=0 deep_clone=1 deep_clone_no_bssid=0 # We do deep cloning without BSSID for daisy chaining. [ "$daisy_chain" -gt 0 ] && deep_clone_no_bssid=1 # TODO - check if this is needed for traffic separation (or maybe use # ConfigSta = 0). [ "$traffic_separation_enabled" -gt 0 ] && { deep_clone=0 deep_clone_no_bssid=0 } __repacd_config_noncap_mode $disable_ap $deep_clone $deep_clone_no_bssid } # Switch the device into acting as a pure client device (no AP interfaces # enabled). __repacd_config_client_mode() { local disable_ap=1 deep_clone=0 __repacd_config_noncap_mode $disable_ap $deep_clone 0 } # Change the configuration on the wifi-iface object to match what is desired. # This function is for Multi-AP mode. # # input: $1 config: section to update # input: $2 network: only update if network matches this value # input: $3 block_dfs_chan: 1 - block DFS channels, 0 - do not block them # input-output: $4 change counter __repacd_config_iface_map() { local enable_wds=1 qwrap_ap=0 extap=0 enable_rrm=1 re_scalingfactor=0 local default_root_dist=0 cap_snr=0 __repacd_config_iface "$1" "$2" $enable_wds $qwrap_ap $extap "$3" $enable_rrm \ $re_scalingfactor $default_root_dist $cap_snr "$4" } # Generate the Multi-AP BSS instantiation config file for wsplcd based on # the selected template and SSID settings. # input-output: $1 change counter __repacd_generate_map_bss_conf() { local changed="$1" local template_filename local template_path local fronthaul_ssid fronthaul_key local backhaul_ssid backhaul_key config_load repacd config_get template_filename MAPConfig BSSInstantiationTemplate config_get fronthaul_ssid MAPConfig FronthaulSSID config_get fronthaul_key MAPConfig FronthaulKey config_get backhaul_ssid MAPConfig BackhaulSSID config_get backhaul_key MAPConfig BackhaulKey if [ -z "${template_filename}" ]; then __repacd_echo "BSS instantiation template not specified" return 1 fi template_path="${WSPLCD_MAP_TEMPLATE_DIR}/${template_filename}" if [ ! -r "${template_path}" ]; then __repacd_echo "BSS instantiation template ${template_path} not readable" return 1 fi __repacd_echo "Using wsplcd BSS instantiation template: ${template_path}" local tempfile tempfile=$(mktemp) cp "${template_path}" "${tempfile}" # Some of these replacements may not be used, but this covers all of the # cases of variables that need to be replaced. # # Note that in case the variable contains the sed delimeter, it needs to # be escaped to avoid a sed error. sed -i -e "s!__FH_SSID_REPLACE__!${fronthaul_ssid/!/\!}!g" \ -e "s!__FH_KEY_REPLACE__!${fronthaul_key/!/\!}!g" \ -e "s!__BH_SSID_REPLACE__!${backhaul_ssid/!/\!}!g" \ -e "s!__BH_KEY_REPLACE__!${backhaul_key/!/\!}!g" \ -e "s!__FHBH_SSID_REPLACE__!${fronthaul_ssid/!/\!}!g" \ -e "s!__FHBH_KEY_REPLACE__!${fronthaul_key/!/\!}!g" \ "${tempfile}" if [ ! -r "${WSPLCD_MAP_BSS_POLICY_PATH}" ] || \ ! cmp -s "${tempfile}" "${WSPLCD_MAP_BSS_POLICY_PATH}"; then # New file differs from old. Move it into place and update # the change count. mv -f "${tempfile}" "${WSPLCD_MAP_BSS_POLICY_PATH}" changed=$((changed + 1)) eval "$1='$changed'" else # No change, so just remove the temporary file rm -f "${tempfile}" fi return 0 } # Switch the device into acting as a gateway connected AP (no bSTA). # # Pre-condition: RE mode has already been checked to be SON # # input: $1 is_controller: whether the device should act as the controller # or just a gateway connected AP # input: $2 standalone_controller: if a controller, whether the device should # act as a standalone controller __repacd_config_gwcon_map_ap() { local is_controller=$1 local wsplcd_mode son_mode local rate_scaling_factor=0 local default_root_dist=0 # The WDS, VAP independent, and QWrap AP settings also need to be updated # based on the range extension mode. local enable_wds=1 enable_multi_ap=1 disable_steering=0 local deep_clone=0 deep_clone_no_bssid=0 config_sta=0 map_enable=1 local block_dfs __repacd_echo "Using SON mode for GW Connected AP" # In WDS/SON modes, we let the OEM customize whether DFS channels # should be permitted. if __repacd_is_block_dfs; then block_dfs=1 else block_dfs=0 fi wsplcd_enabled=1 local disable_24g_sta disable_5g_sta disable_24g_ap disable_5g_ap if [ "$is_controller" -gt 0 ] && [ "$standalone_controller" -gt 0 ]; then __repacd_echo "Disabling all interfaces for standalone controller" disable_24g_sta=1 disable_5g_sta=1 disable_24g_ap=1 disable_5g_ap=1 else # In GW-connected AP mode, only the AP interfaces are enabled. disable_24g_sta=1 disable_5g_sta=1 disable_24g_ap=0 disable_5g_ap=0 fi config_load wireless config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'sta' $disable_24g_sta $disable_5g_sta config_changed config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'ap' $disable_24g_ap $disable_5g_ap config_changed # Now set up the interfaces in the right way. if [ "$standalone_controller" -eq 0 ]; then config_foreach __repacd_config_iface_map wifi-iface \ $managed_network $block_dfs config_changed fi uci_commit wireless uci_set repacd repacd Role 'CAP' if [ "$is_controller" -gt 0 ]; then uci_set hyd MultiAP EnableController 1 # Standalone controller does not act as an Agent if [ "$standalone_controller" -gt 0 ]; then uci_set hyd MultiAP EnableAgent 0 else uci_set hyd MultiAP EnableAgent 1 fi # Force the remote association tracking on for the controller, as the # steering is centralized. uci_set lbd StaDB TrackRemoteAssoc 1 else uci_set hyd MultiAP EnableController 0 uci_set hyd MultiAP EnableAgent 1 # For an agent, use whatever the current remote association tracking # setting is. There is still an advantage to tracking remote # associations as it allows the bridging tables to be cleaned up # properly when a Topology Notification is missed. fi # This generally should nto be needed when operating in gateway connected # AP mode. Until there is a case where we need it, we'll leave it disabled. uci_set repacd FrontHaulMgr ManageFrontAndBackHaulsIndependently 0 uci_commit repacd uci_commit hyd uci_commit lbd if [ "$is_controller" -gt 0 ]; then wsplcd_mode='REGISTRAR' son_mode='HYROUTER' if ! __repacd_generate_map_bss_conf config_changed; then return 1 fi else wsplcd_mode='ENROLLEE' son_mode='HYCLIENT' fi # No deep cloning with the MAP algorithms __repacd_configure_wsplcd $wsplcd_mode $deep_clone $deep_clone_no_bssid \ $config_sta $map_enable config_changed __repacd_configure_son $enable_wds $disable_steering $enable_multi_ap \ $son_mode config_changed return 0 } # Switch the device to act as a range extender. __repacd_config_map_re() { # The WDS and QWrap AP settings also need to be updated based on the # range extension mode. local enable_wds=1 block_dfs local enable_multi_ap=1 disable_steering=0 local deep_clone=0 deep_clone_no_bssid=0 config_sta=0 map_enable=1 local disable_24g_ap=0 disable_5g_ap=0 # We let the OEM customize whether DFS channels should be permitted. if __repacd_is_block_dfs; then block_dfs=1 else block_dfs=0 fi # We let the daemon start wsplcd once it has a stable bSTA association. wsplcd_enabled=0 wsplcd_stop=1 config_load wireless # How the bSTA interface is managed is dependent on the selected and # preference values. local selected_radio='' preferred_radio='' map_bsta_max_preference=0 config_foreach __repacd_resolve_bsta_radio wifi-device \ selected_radio preferred_radio if [ -z "$selected_radio" ]; then selected_radio="$preferred_radio" fi __repacd_echo "Using $selected_radio for bSTA" config_foreach __repacd_update_map_bsta_radio wifi-iface \ $selected_radio $managed_network config_changed config_foreach __repacd_disable_vap wifi-iface \ $managed_network 'ap' $disable_24g_ap $disable_5g_ap config_changed config_foreach __repacd_config_iface_map wifi-iface \ $managed_network $block_dfs config_changed uci_commit wireless uci_set repacd repacd Role 'NonCAP' uci_set repacd FrontHaulMgr ManageFrontAndBackHaulsIndependently 1 uci_commit repacd uci_set hyd MultiAP EnableController 0 uci_set hyd MultiAP EnableAgent 1 uci_commit hyd __repacd_configure_wsplcd 'ENROLLEE' $deep_clone $deep_clone_no_bssid \ $config_sta $map_enable config_changed __repacd_configure_son $enable_wds $disable_steering $enable_multi_ap \ 'HYCLIENT' config_changed } # Restart wsplcd and the Wi-Fi interfaces based on configuration changes. __repacd_restart_dependencies() { if [ "$wsplcd_stop" -gt 0 ]; then $WSPLCD_INIT stop fi if [ "$hyd_stop" -gt 0 ]; then $HYD_INIT stop $HYFI_BRIDGING_INIT stop fi # When hyd is being started, start the bridging hooks prior to restarting # the network to ensure any temporary loops are prevented. if [ "$hyd_start" -gt 0 ]; then $HYFI_BRIDGING_INIT start fi if [ "$config_changed" -gt 0 ]; then __repacd_echo "Restarting network stack..." whc_network_restart else __repacd_echo "No changes; not restarting network stack..." fi if [ "$wsplcd_start" -gt 0 ]; then __repacd_echo "Starting wsplcd" $WSPLCD_INIT start elif [ "$wsplcd_restart" -gt 0 ]; then __repacd_echo "Restarting wsplcd" $WSPLCD_INIT restart fi if [ "$hyd_start" -gt 0 ]; then __repacd_echo "Starting hyd" $HYD_INIT start fi } # Perform the startup actions when operating in the original Wi-Fi SON mode # (no Multi-AP SIG support). __start_son() { local enabled map_enabled device_type local mode activate_ts local eth_mon_enabled config_changed=0 net_config_changed=0 activate_ts=0 config_load 'repacd' config_get_bool enabled repacd 'Enable' '0' config_get traffic_separation_enabled repacd TrafficSeparationEnabled '0' config_get traffic_separation_active repacd TrafficSeparationActive '0' config_get daisy_chain WiFiLink DaisyChain '0' config_get backhaul_ssid repacd BackhaulSSID $def_backhaul_ssid config_get backhaul_enc repacd BackhaulEnc $def_backhaul_enc config_get backhaul_key repacd BackhaulKey $def_backhaul_key config_get network_guest repacd NetworkGuest 'guest' config_get guest_ssid repacd GuestSSID $def_guest_ssid config_get guest_enc repacd GuestEnc $def_guest_enc config_get guest_key repacd GuestKey $def_guest_key config_get guest_backhaul_iface repacd NetworkGuestBackhaulInterface 'both' config_get eth_mon_enabled repacd 'EnableEthernetMonitoring' '0' config_get manage_vap_ind WiFiLink 'ManageVAPInd' '0' config_get Manage_front_and_back_hauls_ind 'FrontHaulMgr' 'ManageFrontAndBackHaulsIndependently' '0' __repacd_get_config_re_mode config_re_mode [ "$enabled" -gt 0 ] || { return 1 } __repacd_echo "starting WHC auto-configuration" # For now, we can only manage a single network. config_get managed_network repacd ManagedNetwork 'lan' __repacd_echo "Managed network: $managed_network" config_get device_type repacd DeviceType 'RE' __repacd_echo "Device type: $device_type" # Grab a lock to prevent any updates from being made by the daemon. whc_wifi_config_lock __repacd_config_wps_pbc_enhc 0 config_changed # Config_changed is not being gracefully handled in MIPS. # so commiting the change if wps_pbc_enhn is set if [ "$config_changed" -gt 0 ]; then uci_commit wireless config_changed=0 fi if __repacd_vaps_in_default_config; then __repacd_reset_default_config config_changed=1 __repacd_echo "Reset $managed_network VAPs" else # Need to massage the configuration to make it consistent with the # expectations of repacd. __repacd_reset_existing_config __repacd_echo "Initialized $managed_network VAPs" fi __repacd_enable_wifi # create additional vaps if traffic separation enabled if __repacd_gw_mode || [ "$device_type" = 'RE' ] && [ "$gwcon_mode" != "CAP" ]; then if [ "$traffic_separation_enabled" -gt 0 ]; then if __repacd_is_qwrap_mode || \ __repacd_is_son_mode; then if __repacd_check_additional_network_exist; then __repacd_set_bridge_empty $network_guest __repacd_set_firewall_rules $network_guest __repacd_reset_additional_config if ! __repacd_gw_mode && __repacd_is_qwrap_mode && \ [ "$traffic_separation_active" -eq 0 ]; then local disable_24g_ap=1 disable_5g_ap=1 config_load wireless config_foreach __repacd_disable_vap wifi-iface \ $network_backhaul 'ap' $disable_24g_ap $disable_5g_ap config_changed config_foreach __repacd_disable_vap wifi-iface \ $network_guest 'ap' $disable_24g_ap $disable_5g_ap config_changed uci_commit wireless fi uci_set repacd repacd NetworkBackhaul $network_backhaul uci_commit repacd activate_ts=1 fi fi fi fi if __repacd_gw_mode; then # WAN group not empty; this device will act as CAP regardless of # the GatewayConnectedMode setting __repacd_config_gwcon_ap_mode 1 elif [ "$device_type" = 'RE' ]; then # WAN group empty or non-existent # Switch to range extender mode # Clear the BSSIDs on fresh restart config_load wireless if [ "$traffic_separation_active" -gt 0 ]; then config_foreach __repacd_delete_bssid_entry wifi-iface $network_backhaul config_changed else config_foreach __repacd_delete_bssid_entry wifi-iface $managed_network config_changed fi uci_set repacd WiFiLink BSSIDResolveState 'resolving' uci_commit wireless uci_commit repacd __repacd_config_re_mode if [ "$activate_ts" -eq 1 ]; then config_load wireless config_foreach __repacd_reconfig_sta_vaps wifi-iface $managed_network $network_backhaul \ "$backhaul_ssid" "$backhaul_enc" "$backhaul_key" uci_commit wireless fi else # Must be a client device (that can opportunistically act as an RE). __repacd_config_client_mode fi whc_wifi_config_unlock __repacd_restart_dependencies if [ "$traffic_separation_enabled" -gt 0 ]; then __repacd_wifi_set_otherband_bssids $network_backhaul else __repacd_wifi_set_otherband_bssids $managed_network fi # create vlan interfaces required for traffic separation. if [ "$activate_ts" -eq 1 ]; then config_load network config_load wireless config_foreach __repacd_add_vlan_interfaces wifi-iface \ $managed_network $lan_vid 'both' net_config_changed config_foreach __repacd_add_vlan_interfaces wifi-iface \ $network_guest $guest_vid $guest_backhaul_iface net_config_changed uci_commit wireless __repacd_add_ethernet_vlan_interfaces $network_guest net_config_changed uci_commit network __repacd_restart_firewall uci_set repacd repacd TrafficSeparationActive '1' uci_commit repacd # stop/start hyd only if there is any change in netwrok config # due to addition of VLAN interfaces. If required VLAN iface already # present then we can avoid hyd stop/start. This will save some time # and avoid any delays after repacd restart. if [ "$net_config_changed" -gt 0 ] || [ "$config_changed" -gt 0 ]; then config_changed=0 hyd_stop=1 hyd_start=1 wsplcd_stop=1 wsplcd_start=1 __repacd_restart_dependencies fi fi if [ "$eth_mon_enabled" -eq 1 ]; then # Make sure lldpd listens on wan and lan interfaces for int in wan lan; do if ! uci get lldpd.config.interface | grep $int > /dev/null; then uci add_list lldpd.config.interface=$int fi done __repacd_echo "Starting lldpd" repacd_netdet_lldpd_init start fi if ! __repacd_gw_mode || [ "$eth_mon_enabled" -eq 1 ]; then start-stop-daemon -K -n repacd-run.sh -s SIGTERM >/dev/null # Start the script that monitors the link state. # # When in NonCAP mode, it will keep checking whether there is a link # to the gateway over ethernet. When in CAP mode, it will keep # checking the WAN/LAN ifaces. __repacd_echo "Starting RE Placement and Auto-config Daemon" start-stop-daemon -S -x /usr/sbin/repacd-run.sh -b -- \ "son" init $config_re_mode $resolved_re_mode $resolved_re_submode fi } # Perform the startup actions when operating with Multi-AP SIG Topology # Optimization. # # Pre-condition: repacd has already been determined to be enabled and in # MAP mode # # input: $1 - ether_gwcon: whether the device has been determined to be # connected to the gateway via Ethernet # input: $2 - start_role: the startup role for the device # input: $3 - autoconf: boolean indicating whether this was a start # initiated due to an auto config change __start_map() { local ether_gwcon=$1 local start_role=$2 local autoconf=$3 local enabled gwcon_mode first_config_required manage_mcsd local traffic_separation_enabled ethernet_monitoring_enabled local enable_steering standalone_controller config_changed=0 config_load 'repacd' config_get_bool enabled repacd 'Enable' '0' config_get gwcon_mode repacd GatewayConnectedMode 'AP' config_get_bool first_config_required MAPConfig 'FirstConfigRequired' '0' config_get_bool manage_mcsd repacd 'ManageMCSD' 1 config_get_bool standalone_controller MAPConfig 'StandaloneController' '0' # Certain features are not supported with Multi-AP (at least not yet) config_get traffic_separation_enabled repacd TrafficSeparationEnabled '0' config_get ethernet_monitoring_enabled repacd EnableEthernetMonitoring '0' config_get enable_steering repacd EnableSteering '1' if ! __repacd_is_son_mode; then __repacd_echo "Multi-AP SIG algorithms must use 'son' RE mode" return 1 fi if [ "$traffic_separation_enabled" -gt 0 ]; then __repacd_echo "Traffic separation not supported with Multi-AP SIG" \ "Topology Optimization" return 1 fi if [ "$ethernet_monitoring_enabled" -gt 0 ]; then __repacd_echo "Ethernet monitoring not supported with Multi-AP SIG" \ "Topology Optimization" return 1 fi if [ "$enable_steering" -eq 0 ]; then __repacd_echo "Steering must be enabled with Multi-AP SIG" \ "Topology Optimization" return 1 fi __repacd_echo "Starting Multi-AP SIG auto-configuration" __repacd_echo "Ethernet connection to GW=$ether_gwcon" __repacd_echo "GW Connected Mode=$gwcon_mode" # For now, we can only manage a single network. config_get managed_network repacd ManagedNetwork 'lan' __repacd_echo "Managed network: $managed_network" local is_controller=0 if __repacd_gw_mode || [ "$gwcon_mode" = 'Controller' ]; then # WAN group not empty; this device will act as controller regardless of # the GatewayConnectedMode setting is_controller=1 fi # Grab a lock to prevent any updates from being made by the daemon. whc_wifi_config_lock # Since the controller could tear down all AP interfaces, we need to # allow hyd to run with no interfaces. uci_set lbd config_Adv 'AllowZeroAPInterfaces' 1 # Also disable IAS on both bands, as we do not yet have the messaging # support for it. uci_set lbd IAS 'Enable_W2' 0 uci_set lbd IAS 'Enable_W5' 0 uci_commit lbd # Disable the DBDC repeater feature on all devices, as there will only # ever be a single backhaul STA interface. config_load wireless config_foreach __repacd_config_dbdc_device wifi-device \ 0 config_changed # Skip auto config for standalone controller, which must be manually configured if [ "$first_config_required" -gt 0 ] && [ "$standalone_controller" -eq 0 ]; then __repacd_reset_map_default_config $is_controller config_changed=1 uci_set repacd MAPConfig 'FirstConfigRequired' 0 __repacd_echo "Performed initial config on $managed_network VAPs" fi if __repacd_gw_mode || [ "$ether_gwcon" -gt 0 ]; then if ! __repacd_config_gwcon_map_ap $is_controller $standalone_controller; then return 1 fi else # WAN group empty or non-existent # Switch to agent mode __repacd_config_map_re fi local enable_son=1 __repacd_config_mcsd "$manage_mcsd" "$enable_son" whc_wifi_config_unlock __repacd_restart_dependencies if ! __repacd_gw_mode; then start-stop-daemon -K -n repacd-run.sh -s SIGTERM >/dev/null # Transform the boolean value into what the daemon expects if [ "$autoconf" -gt 0 ]; then autoconf='autoconf' else autoconf='' fi # Start the script that monitors the link state. # # In this NonCAP mode, it will keep checking whether there is a link # to the gateway over ethernet. __repacd_echo "Starting RE Placement and Auto-config Daemon" start-stop-daemon -S -x /usr/sbin/repacd-run.sh -b -- \ "map" "$start_role" $config_re_mode $resolved_re_mode \ $resolved_re_submode $autoconf fi } # Reset the count of the number of times the 5 GHz bSTA was attempted. # This should only be invoked on boot and when switching between roles # (eg. to CAP). __repacd_map_reset_5g_attempts() { uci_set repacd 'MAPWiFiLink' '5gAttemptsCount' 0 uci_commit repacd } # Script entry point: Perform configuration and start the daemon start() { local enabled config_load 'repacd' config_get_bool enabled repacd 'Enable' '0' [ "$enabled" -gt 0 ] || { return 1 } if __repacd_is_map_enabled; then __repacd_map_reset_5g_attempts local ether_gwcon=0 start_role='init' autoconf=0 __start_map $ether_gwcon $start_role $autoconf return $? else __start_son return $? fi } # Script entry point: Stop the daemon stop() { start-stop-daemon -K -n repacd-run.sh -s SIGTERM >/dev/null if [ -f $WSPLCD_INIT ]; then $WSPLCD_INIT stop fi } # Script entry point: Reconfigure and restart the daemon restart() { stop config_load 'repacd' config_get_bool enabled repacd 'Enable' '0' [ "$enabled" -gt 0 ] || { return 1 } start } # Force a restart into CAP mode using the SON algorithms. # # @see restart_in_cap_mode __restart_in_cap_mode_son() { local gwcon_mode device_type activate_ts config_load repacd config_get managed_network repacd ManagedNetwork 'lan' config_get gwcon_mode repacd GatewayConnectedMode 'AP' config_get device_type repacd DeviceType 'RE' config_get traffic_separation_enabled repacd TrafficSeparationEnabled '0' config_get traffic_separation_active repacd TrafficSeparationActive '0' config_get daisy_chain WiFiLink DaisyChain '0' config_get backhaul_ssid repacd BackhaulSSID $def_backhaul_ssid config_get backhaul_enc repacd BackhaulEnc $def_backhaul_enc config_get backhaul_key repacd BackhaulKey $def_backhaul_key config_get network_guest repacd NetworkGuest 'guest' config_get guest_ssid repacd GuestSSID $def_guest_ssid config_get guest_enc repacd GuestEnc $def_guest_enc config_get guest_key repacd GuestKey $def_guest_key config_get guest_backhaul_iface repacd NetworkGuestBackhaulInterface 'both' config_get manage_vap_ind WiFiLink 'ManageVAPInd' '0' __repacd_get_config_re_mode config_re_mode activate_ts=0 net_config_changed=0 stop if [ "$gwcon_mode" = "CAP" ]; then # Explicitly being forced into CAP mode while gateway connected. # This could be a case where a device is being used as a pure bridge # due to another device acting as the gateway. __repacd_config_wps_pbc_enhc 1 config_changed __repacd_config_gwcon_ap_mode 1 else # Operate just as a standalone AP. This assumes there is another # device in the network that operates as CAP. __repacd_config_wps_pbc_enhc 0 config_changed __repacd_config_gwcon_ap_mode 0 fi __repacd_reset_existing_config if [ "$device_type" = 'RE' ] && [ "$gwcon_mode" != "CAP" ]; then if [ "$traffic_separation_enabled" -gt 0 ] && \ __repacd_is_son_mode; then if __repacd_check_additional_network_exist; then # reset additional vaps if traffic separation enabled local disable_24g_ap=0 disable_5g_ap=0 local disable_24g_sta=1 disable_5g_sta=1 config_load network config_load wireless config_foreach __repacd_disable_vap wifi-iface \ $network_backhaul 'ap' $disable_24g_ap $disable_5g_ap config_changed config_foreach __repacd_disable_vap wifi-iface \ $network_guest 'ap' $disable_24g_ap $disable_5g_ap config_changed if [ "$traffic_separation_active" -eq 1 ]; then config_foreach __repacd_delete_vlan_interfaces wifi-iface \ $managed_network $lan_vid 'ap' net_config_changed config_foreach __repacd_delete_vlan_interfaces wifi-iface \ $network_guest $guest_vid 'ap' net_config_changed config_foreach __repacd_delete_vlan_interfaces wifi-iface \ $managed_network $lan_vid 'sta' net_config_changed config_foreach __repacd_delete_vlan_interfaces wifi-iface \ $network_guest $guest_vid 'sta' net_config_changed config_foreach __repacd_disable_vap wifi-iface \ $network_backhaul 'sta' $disable_24g_sta $disable_5g_sta config_changed fi uci_commit wireless uci_commit network __repacd_reset_additional_config activate_ts=1 fi fi fi if [ "$wsplcd_enabled" -gt 0 ]; then wsplcd_restart=1 fi __repacd_restart_dependencies if [ "$traffic_separation_enabled" -gt 0 ]; then __repacd_wifi_set_otherband_bssids $network_backhaul else __repacd_wifi_set_otherband_bssids $managed_network fi if [ "$activate_ts" -eq 1 ]; then config_load network config_load wireless config_foreach __repacd_add_vlan_interfaces wifi-iface \ $managed_network $lan_vid 'both' net_config_changed config_foreach __repacd_add_vlan_interfaces wifi-iface \ $network_guest $guest_vid $guest_backhaul_iface net_config_changed uci_commit wireless __repacd_add_ethernet_vlan_interfaces $network_guest net_config_changed uci_commit network __repacd_restart_firewall uci_set repacd repacd TrafficSeparationActive '1' uci_commit repacd if [ "$net_config_changed" -gt 0 ] || [ "$config_changed" -gt 0 ]; then config_changed=0 hyd_stop=1 hyd_start=1 wsplcd_stop=1 wsplcd_start=1 __repacd_restart_dependencies fi fi if ! __repacd_gw_mode; then # Start the daemon that monitors link status in CAP mode, telling # the daemon that it is an auto config-triggered restart. # # In this mode, it will just keep checking that the link to the # gateway is still present on ethernet. start-stop-daemon -S -x /usr/sbin/repacd-run.sh -b -- \ "son" CAP $config_re_mode $resolved_re_mode $resolved_re_submode \ autoconf fi } # Force a restart into CAP mode using the Multi-AP SIG Topoology Optimization # algorithm. # # @see restart_in_cap_mode __restart_in_cap_mode_map() { stop # Reset the counter here in case we switch back into NonCAP (aka. RE) # mode. It is easier to do it here than on the NonCAP restart since # the latter is also used to force a bSTA change. __repacd_map_reset_5g_attempts local ether_gwcon=1 start_role='CAP' autoconf=1 __start_map $ether_gwcon $start_role $autoconf } # Force a restart into CAP mode. # # This is used when the gateway detection logic detects a gateway on # ethernet when running in a pure bridge mode. restart_in_cap_mode() { if __repacd_is_map_enabled; then __restart_in_cap_mode_map return $? else __restart_in_cap_mode_son return $? fi } # Force a restart into NonCAP mode using the SON algorithms. # # @see restart_in_noncap_mode __restart_in_noncap_mode_son() { local device_type activate_ts config_load repacd config_get managed_network repacd ManagedNetwork 'lan' config_get device_type repacd DeviceType 'RE' config_get gwcon_mode repacd GatewayConnectedMode 'AP' config_get traffic_separation_enabled repacd TrafficSeparationEnabled '0' config_get traffic_separation_active repacd TrafficSeparationActive '0' config_get daisy_chain WiFiLink DaisyChain '0' config_get backhaul_ssid repacd BackhaulSSID $def_backhaul_ssid config_get backhaul_enc repacd BackhaulEnc $def_backhaul_enc config_get backhaul_key repacd BackhaulKey $def_backhaul_key config_get network_guest repacd NetworkGuest 'guest' config_get guest_ssid repacd GuestSSID $def_guest_ssid config_get guest_enc repacd GuestEnc $def_guest_enc config_get guest_key repacd GuestKey $def_guest_key config_get guest_backhaul_iface repacd NetworkGuestBackhaulInterface 'both' config_get manage_vap_ind WiFiLink 'ManageVAPInd' '0' __repacd_get_config_re_mode config_re_mode activate_ts=0 stop net_config_changed=0 # Apply the SSID and passphrase to all interfaces to ensure that if we are # switching into a SON mode where there are two STA interfaces, they all # have the right credentials. For the non-SON and WDS modes, this is # subject to the RE WPS enhancement rules. __repacd_config_wps_pbc_enhc 0 config_changed __repacd_reset_existing_config # Need to resolve the generic NonCAP role to the actual configuration. if [ "$device_type" = 'RE' ]; then __repacd_config_re_mode if [ "$gwcon_mode" != "CAP" ]; then if [ "$traffic_separation_enabled" -gt 0 ] && \ __repacd_is_son_mode; then if __repacd_check_additional_network_exist; then # reset additional vaps if traffic separation enabled local disable_24g_ap=0 disable_5g_ap=0 config_load wireless # Enable spcl AP VAPs on NON-CAP only if daisy chain is enabled. # They are for multi hop support. We don't need them if daisy # chain is disabled. if [ "$daisy_chain" -gt 0 ]; then config_foreach __repacd_disable_vap wifi-iface \ $network_backhaul 'ap' $disable_24g_ap $disable_5g_ap config_changed fi config_foreach __repacd_disable_vap wifi-iface \ $network_guest 'ap' $disable_24g_ap $disable_5g_ap config_changed uci_commit wireless __repacd_reset_additional_config config_load wireless config_foreach __repacd_reconfig_sta_vaps wifi-iface $managed_network $network_backhaul \ "$backhaul_ssid" "$backhaul_enc" "$backhaul_key" uci_commit wireless activate_ts=1 fi fi fi else __repacd_config_client_mode fi if [ "$wsplcd_enabled" -gt 0 ]; then wsplcd_restart=1 fi __repacd_restart_dependencies if [ "$traffic_separation_enabled" -gt 0 ]; then __repacd_wifi_set_otherband_bssids $network_backhaul else __repacd_wifi_set_otherband_bssids $managed_network fi # create vlan interfaces required for traffic separation. if [ "$activate_ts" -eq 1 ]; then config_load network config_load wireless config_foreach __repacd_add_vlan_interfaces wifi-iface \ $managed_network $lan_vid 'both' net_config_changed config_foreach __repacd_add_vlan_interfaces wifi-iface \ $network_guest $guest_vid $guest_backhaul_iface net_config_changed uci_commit wireless __repacd_add_ethernet_vlan_interfaces $network_guest net_config_changed uci_commit network __repacd_restart_firewall uci_set repacd repacd TrafficSeparationActive '1' uci_commit repacd # stop/start hyd only if there is any change in netwrok config # due to addition of VLAN interfaces. If required VLAN iface already # present then we can avoid hyd stop/start. This will save some time # and avoid any unnecessary delays after repacd restart. if [ "$net_config_changed" -gt 0 ] || [ "$config_changed" -gt 0 ]; then config_changed=0 hyd_stop=1 hyd_start=1 wsplcd_stop=1 wsplcd_start=1 __repacd_restart_dependencies fi fi if ! __repacd_gw_mode; then # Start the script that monitors the link state, telling the daemon that # it is an auto config-triggered restart. # # In this NonCAP mode, it will keep checking whether there is a link # to the gateway over ethernet. start-stop-daemon -S -x /usr/sbin/repacd-run.sh -b -- \ "son" NonCAP $config_re_mode $resolved_re_mode \ $resolved_re_submode autoconf fi } # Force a restart in NonCAP mode using the Multi-AP SIG Topology Optimization # algorithm. # # @see restart_in_noncap_mode __restart_in_noncap_mode_map() { stop local ether_gwcon=0 start_role='NonCAP' autoconf=1 __start_map $ether_gwcon $start_role $autoconf } # Force a restart into NonCAP mode. # # This is used when the gateway detection logic detects that there is no # longer a gateway connected over ethernet. restart_in_noncap_mode() { if __repacd_is_map_enabled; then __restart_in_noncap_mode_map return $? else __restart_in_noncap_mode_son return $? fi } # Force a restart into Range Extender (RE) mode with the SON algorithms. # # @see restart_in_re_mode __restart_in_re_mode_son() { config_load repacd config_get managed_network repacd ManagedNetwork 'lan' stop # By resetting the configuration, this will apply the same SSID and # passphrase to all interfaces. Then enable the interfaces as appropriate # for RE mode. __repacd_config_wps_pbc_enhc 0 config_changed __repacd_reset_existing_config __repacd_config_re_mode if [ "$wsplcd_enabled" -gt 0 ]; then wsplcd_restart=1 fi __repacd_restart_dependencies __repacd_wifi_set_otherband_bssids $managed_network if ! __repacd_gw_mode; then # Start the script that monitors the link state, telling the daemon # that it is an auto config-triggered restart. # # In this Range Extender mode, it will keep checking whether there is # a link to the gateway over ethernet and that the Wi-Fi link is # sufficient to continue operating as an RE. start-stop-daemon -S -x /usr/sbin/repacd-run.sh -b -- \ "son" RE $config_re_mode $resolved_re_mode $resolved_re_submode \ autoconf fi } # Force a restart into Range Extender (RE) mode with the Multi-AP SIG Topology # Optimization algorithm. # # @see restart_in_re_mode __restart_in_re_mode_map() { stop local ether_gwcon=0 start_role='RE' autoconf=1 __start_map $ether_gwcon $start_role $autoconf } # Force a restart into Range Extender (RE) mode. # # This is used when the Wi-Fi link monitoring logic determines that the # link is in the sweet spot for a device that normally acts as a client # but is capable (from a CPU and Wi-Fi perspective) of operating as an AP # and a STA at the same time. restart_in_re_mode() { if __repacd_is_map_enabled; then __restart_in_re_mode_map return $? else __restart_in_re_mode_son return $? fi }