+++ /dev/null
-#!/bin/sh
-# Copyright (C) 2006 OpenWrt.org
-
-. /lib/functions.sh
-. /usr/share/libubox/jshn.sh
-
-usage() {
- cat <<EOF
-Usage: $0 [config|up|down|reconf|reload|status|isup]
-enables (default), disables or configures devices not yet configured.
-EOF
- exit 1
-}
-
-ubus_wifi_cmd() {
- local cmd="$1"
- local dev="$2"
-
- json_init
- [ -n "$dev" ] && json_add_string device "$dev"
- ubus call network.wireless "$cmd" "$(json_dump)"
-}
-
-wifi_isup() {
- local dev="$1"
-
- json_load "$(ubus_wifi_cmd "status" "$dev")"
- json_get_keys devices
-
- for device in $devices; do
- json_select "$device"
- json_get_var up up
- [ $up -eq 0 ] && return 1
- json_select ..
- done
-
- return 0
-}
-
-find_net_config() {(
- local vif="$1"
- local cfg
- local ifname
-
- config_get cfg "$vif" network
-
- [ -z "$cfg" ] && {
- include /lib/network
- scan_interfaces
-
- config_get ifname "$vif" ifname
-
- cfg="$(find_config "$ifname")"
- }
- [ -z "$cfg" ] && return 0
- echo "$cfg"
-)}
-
-
-bridge_interface() {(
- local cfg="$1"
- [ -z "$cfg" ] && return 0
-
- include /lib/network
- scan_interfaces
-
- for cfg in $cfg; do
- config_get iftype "$cfg" type
- [ "$iftype" = bridge ] && config_get "$cfg" ifname
- prepare_interface_bridge "$cfg"
- return $?
- done
-)}
-
-prepare_key_wep() {
- local key="$1"
- local hex=1
-
- echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
- [ "${#key}" -eq 10 -a $hex -eq 1 ] || \
- [ "${#key}" -eq 26 -a $hex -eq 1 ] || {
- [ "${key:0:2}" = "s:" ] && key="${key#s:}"
- key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
- }
- echo "$key"
-}
-
-wifi_fixup_hwmode() {
- local device="$1"
- local default="$2"
- local hwmode hwmode_11n
-
- config_get channel "$device" channel
- config_get hwmode "$device" hwmode
- case "$hwmode" in
- 11bg) hwmode=bg;;
- 11a) hwmode=a;;
- 11ad) hwmode=ad;;
- 11b) hwmode=b;;
- 11g) hwmode=g;;
- 11n*)
- hwmode_11n="${hwmode##11n}"
- case "$hwmode_11n" in
- a|g) ;;
- default) hwmode_11n="$default"
- esac
- config_set "$device" hwmode_11n "$hwmode_11n"
- ;;
- *)
- hwmode=
- if [ "${channel:-0}" -gt 0 ]; then
- if [ "${channel:-0}" -gt 14 ]; then
- hwmode=a
- else
- hwmode=g
- fi
- else
- hwmode="$default"
- fi
- ;;
- esac
- config_set "$device" hwmode "$hwmode"
-}
-
-_wifi_updown() {
- for device in ${2:-$DEVICES}; do (
- config_get disabled "$device" disabled
- [ "$disabled" = "1" ] && {
- echo "'$device' is disabled"
- set disable
- }
- config_get iftype "$device" type
- if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
- eval "scan_$iftype '$device'"
- eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
- elif [ ! -f /lib/netifd/wireless/$iftype.sh ]; then
- echo "$device($iftype): Interface type not supported"
- fi
- ); done
-}
-
-wifi_updown() {
- cmd=down
- [ enable = "$1" ] && {
- _wifi_updown disable "$2"
- ubus_wifi_cmd "$cmd" "$2"
- ubus call network reload
- scan_wifi
- cmd=up
- }
- [ reconf = "$1" ] && {
- ubus call network reload
- scan_wifi
- cmd=reconf
- }
- ubus_wifi_cmd "$cmd" "$2"
- _wifi_updown "$@"
-}
-
-wifi_reload_legacy() {
- _wifi_updown "disable" "$1"
- scan_wifi
- _wifi_updown "enable" "$1"
-}
-
-wifi_reload() {
- ubus call network reload
- wifi_reload_legacy
-}
-
-wifi_detect_notice() {
- >&2 echo "WARNING: Wifi detect is deprecated. Use wifi config instead"
- >&2 echo "For more information, see commit 5f8f8a366136a07df661e31decce2458357c167a"
- exit 1
-}
-
-wifi_config() {
- [ -e /tmp/.config_pending ] && return
- [ ! -f /etc/config/wireless ] && touch /etc/config/wireless
-
- for driver in $DRIVERS; do (
- if eval "type detect_$driver" 2>/dev/null >/dev/null; then
- eval "detect_$driver" || echo "$driver: Detect failed" >&2
- else
- echo "$driver: Hardware detection not supported" >&2
- fi
- ); done
-}
-
-start_net() {(
- local iface="$1"
- local config="$2"
- local vifmac="$3"
-
- [ -f "/var/run/$iface.pid" ] && kill "$(cat /var/run/${iface}.pid)" 2>/dev/null
- [ -z "$config" ] || {
- include /lib/network
- scan_interfaces
- for config in $config; do
- setup_interface "$iface" "$config" "" "$vifmac"
- done
- }
-)}
-
-set_wifi_up() {
- local cfg="$1"
- local ifname="$2"
- uci_set_state wireless "$cfg" up 1
- uci_set_state wireless "$cfg" ifname "$ifname"
-}
-
-set_wifi_down() {
- local cfg="$1"
- local vifs vif vifstr
-
- [ -f "/var/run/wifi-${cfg}.pid" ] &&
- kill "$(cat "/var/run/wifi-${cfg}.pid")" 2>/dev/null
- uci_revert_state wireless "$cfg"
- config_get vifs "$cfg" vifs
- for vif in $vifs; do
- uci_revert_state wireless "$vif"
- done
-}
-
-scan_wifi() {
- local cfgfile="$1"
- DEVICES=
- config_cb() {
- local type="$1"
- local section="$2"
-
- # section start
- case "$type" in
- wifi-device)
- append DEVICES "$section"
- config_set "$section" vifs ""
- config_set "$section" ht_capab ""
- ;;
- esac
-
- # section end
- config_get TYPE "$CONFIG_SECTION" TYPE
- case "$TYPE" in
- wifi-iface)
- config_get device "$CONFIG_SECTION" device
- config_get vifs "$device" vifs
- append vifs "$CONFIG_SECTION"
- config_set "$device" vifs "$vifs"
- ;;
- esac
- }
- config_load "${cfgfile:-wireless}"
-}
-
-DEVICES=
-DRIVERS=
-include /lib/wifi
-scan_wifi
-
-case "$1" in
- down) wifi_updown "disable" "$2";;
- detect) wifi_detect_notice ;;
- config) wifi_config ;;
- status) ubus_wifi_cmd "status" "$2";;
- isup) wifi_isup "$2"; exit $?;;
- reload) wifi_reload "$2";;
- reload_legacy) wifi_reload_legacy "$2";;
- --help|help) usage;;
- reconf) wifi_updown "reconf" "$2";;
- ''|up) wifi_updown "enable" "$2";;
- *) usage; exit 1;;
-esac
define KernelPackage/brcm-wl/Default
$(call Package/broadcom-wl/Default)
SECTION:=kernel
- DEPENDS:=@(TARGET_bcm47xx||TARGET_bcm63xx) +wireless-tools +@KERNEL_WIRELESS_EXT
+ DEPENDS:=@(TARGET_bcm47xx||TARGET_bcm63xx) +wireless-tools +wifi-scripts +@KERNEL_WIRELESS_EXT
TITLE:=Kernel driver for BCM43xx chipsets
FILES:=$(PKG_BUILD_DIR)/driver$(1)/wl.ko $(PKG_BUILD_DIR)/glue/wl_glue.ko
AUTOLOAD:=$(call AutoProbe,wl)
define KernelPackage/cfg80211
$(call KernelPackage/mac80211/Default)
TITLE:=cfg80211 - wireless configuration API
- DEPENDS+= +iw +iwinfo +wireless-regdb +USE_RFKILL:kmod-rfkill
+ DEPENDS+= +iw +iwinfo +wifi-scripts +wireless-regdb +USE_RFKILL:kmod-rfkill
ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
FILES:= \
$(PKG_BUILD_DIR)/compat/compat.ko \
endef
-define KernelPackage/cfg80211/install
- $(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless
- $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
- $(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless
- $(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211
- $(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/10-wifi-detect
-endef
-
$(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv))))
$(eval $(call KernelPackage,cfg80211))
$(eval $(call KernelPackage,mac80211))
+++ /dev/null
-#!/bin/sh
-. /lib/netifd/netifd-wireless.sh
-. /lib/netifd/hostapd.sh
-. /lib/functions/system.sh
-
-init_wireless_driver "$@"
-
-MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
- mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
- mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
- mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
- mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
- mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
- mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
-MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
-MP_CONFIG_STRING="mesh_power_mode"
-
-wdev_tool() {
- ucode /usr/share/hostap/wdev.uc "$@"
-}
-
-ubus_call() {
- flock /var/run/hostapd.lock ubus call "$@"
-}
-
-drv_mac80211_init_device_config() {
- hostapd_common_add_device_config
-
- config_add_string path phy 'macaddr:macaddr'
- config_add_string tx_burst
- config_add_string distance
- config_add_int beacon_int chanbw frag rts
- config_add_int rxantenna txantenna txpower min_tx_power
- config_add_int num_global_macaddr multiple_bssid
- config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
- config_add_array ht_capab
- config_add_array channels
- config_add_array scan_list
- config_add_boolean \
- rxldpc \
- short_gi_80 \
- short_gi_160 \
- tx_stbc_2by1 \
- su_beamformer \
- su_beamformee \
- mu_beamformer \
- mu_beamformee \
- he_su_beamformer \
- he_su_beamformee \
- he_mu_beamformer \
- vht_txop_ps \
- htc_vht \
- rx_antenna_pattern \
- tx_antenna_pattern \
- he_spr_sr_control \
- he_spr_psr_enabled \
- he_bss_color_enabled \
- he_twt_required
- config_add_int \
- beamformer_antennas \
- beamformee_antennas \
- vht_max_a_mpdu_len_exp \
- vht_max_mpdu \
- vht_link_adapt \
- vht160 \
- rx_stbc \
- tx_stbc \
- he_bss_color \
- he_spr_non_srg_obss_pd_max_offset
- config_add_boolean \
- ldpc \
- greenfield \
- short_gi_20 \
- short_gi_40 \
- max_amsdu \
- dsss_cck_40
-}
-
-drv_mac80211_init_iface_config() {
- hostapd_common_add_bss_config
-
- config_add_string 'macaddr:macaddr' ifname
-
- config_add_boolean wds powersave enable
- config_add_string wds_bridge
- config_add_int maxassoc
- config_add_int max_listen_int
- config_add_int dtim_period
- config_add_int start_disabled
-
- # mesh
- config_add_string mesh_id
- config_add_int $MP_CONFIG_INT
- config_add_boolean $MP_CONFIG_BOOL
- config_add_string $MP_CONFIG_STRING
-}
-
-mac80211_add_capabilities() {
- local __var="$1"; shift
- local __mask="$1"; shift
- local __out= oifs
-
- oifs="$IFS"
- IFS=:
- for capab in "$@"; do
- set -- $capab
-
- [ "$(($4))" -gt 0 ] || continue
- [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
- __out="$__out[$1]"
- done
- IFS="$oifs"
-
- export -n -- "$__var=$__out"
-}
-
-mac80211_add_he_capabilities() {
- local __out= oifs
-
- oifs="$IFS"
- IFS=:
- for capab in "$@"; do
- set -- $capab
- [ "$(($4))" -gt 0 ] || continue
- [ "$(((0x$2) & $3))" -gt 0 ] || {
- eval "$1=0"
- continue
- }
- append base_cfg "$1=1" "$N"
- done
- IFS="$oifs"
-}
-
-mac80211_hostapd_setup_base() {
- local phy="$1"
-
- json_select config
-
- [ "$auto_channel" -gt 0 ] && channel=acs_survey
-
- [ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs
- [ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
- append base_cfg "acs_exclude_dfs=1" "$N"
-
- json_get_vars noscan ht_coex min_tx_power:0 tx_burst
- json_get_values ht_capab_list ht_capab
- json_get_values channel_list channels
-
- [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \
- channel_list="$channel"
-
- [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" "$N"
-
- set_default noscan 0
-
- [ "$noscan" -gt 0 ] && hostapd_noscan=1
- [ "$tx_burst" = 0 ] && tx_burst=
-
- chan_ofs=0
- [ "$band" = "6g" ] && chan_ofs=1
-
- ieee80211n=1
- ht_capab=
- case "$htmode" in
- VHT20|HT20|HE20) ;;
- HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160)
- case "$hwmode" in
- a)
- case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
- 1) ht_capab="[HT40+]";;
- 0) ht_capab="[HT40-]";;
- esac
- ;;
- *)
- case "$htmode" in
- HT40+) ht_capab="[HT40+]";;
- HT40-) ht_capab="[HT40-]";;
- *)
- if [ "$channel" -lt 7 ]; then
- ht_capab="[HT40+]"
- else
- ht_capab="[HT40-]"
- fi
- ;;
- esac
- ;;
- esac
- [ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
- ;;
- *) ieee80211n= ;;
- esac
-
- [ -n "$ieee80211n" ] && {
- append base_cfg "ieee80211n=1" "$N"
-
- set_default ht_coex 0
- append base_cfg "ht_coex=$ht_coex" "$N"
-
- json_get_vars \
- ldpc:1 \
- greenfield:0 \
- short_gi_20:1 \
- short_gi_40:1 \
- tx_stbc:1 \
- rx_stbc:3 \
- max_amsdu:1 \
- dsss_cck_40:1
-
- ht_cap_mask=0
- for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do
- ht_cap_mask="$(($ht_cap_mask | $cap))"
- done
-
- cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
- [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
- ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
-
- mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
- LDPC:0x1::$ldpc \
- GF:0x10::$greenfield \
- SHORT-GI-20:0x20::$short_gi_20 \
- SHORT-GI-40:0x40::$short_gi_40 \
- TX-STBC:0x80::$tx_stbc \
- RX-STBC1:0x300:0x100:1 \
- RX-STBC12:0x300:0x200:1 \
- RX-STBC123:0x300:0x300:1 \
- MAX-AMSDU-7935:0x800::$max_amsdu \
- DSSS_CCK-40:0x1000::$dsss_cck_40
-
- ht_capab="$ht_capab$ht_capab_flags"
- [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
- }
-
- # 802.11ac
- enable_ac=0
- vht_oper_chwidth=0
- vht_center_seg0=
-
- idx="$channel"
- case "$htmode" in
- VHT20|HE20) enable_ac=1;;
- VHT40|HE40)
- case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
- 1) idx=$(($channel + 2));;
- 0) idx=$(($channel - 2));;
- esac
- enable_ac=1
- vht_center_seg0=$idx
- ;;
- VHT80|HE80)
- case "$(( (($channel / 4) + $chan_ofs) % 4 ))" in
- 1) idx=$(($channel + 6));;
- 2) idx=$(($channel + 2));;
- 3) idx=$(($channel - 2));;
- 0) idx=$(($channel - 6));;
- esac
- enable_ac=1
- vht_oper_chwidth=1
- vht_center_seg0=$idx
- ;;
- VHT160|HE160)
- if [ "$band" = "6g" ]; then
- case "$channel" in
- 1|5|9|13|17|21|25|29) idx=15;;
- 33|37|41|45|49|53|57|61) idx=47;;
- 65|69|73|77|81|85|89|93) idx=79;;
- 97|101|105|109|113|117|121|125) idx=111;;
- 129|133|137|141|145|149|153|157) idx=143;;
- 161|165|169|173|177|181|185|189) idx=175;;
- 193|197|201|205|209|213|217|221) idx=207;;
- esac
- else
- case "$channel" in
- 36|40|44|48|52|56|60|64) idx=50;;
- 100|104|108|112|116|120|124|128) idx=114;;
- esac
- fi
- enable_ac=1
- vht_oper_chwidth=2
- vht_center_seg0=$idx
- ;;
- esac
- [ "$band" = "5g" ] && {
- json_get_vars background_radar:0
-
- [ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N"
- }
- [ "$band" = "6g" ] && {
- op_class=
- case "$htmode" in
- HE20) op_class=131;;
- HE*) op_class=$((132 + $vht_oper_chwidth))
- esac
- [ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N"
- }
- [ "$hwmode" = "a" ] || enable_ac=0
-
- if [ "$enable_ac" != "0" ]; then
- json_get_vars \
- rxldpc:1 \
- short_gi_80:1 \
- short_gi_160:1 \
- tx_stbc_2by1:1 \
- su_beamformer:1 \
- su_beamformee:1 \
- mu_beamformer:1 \
- mu_beamformee:1 \
- vht_txop_ps:1 \
- htc_vht:1 \
- beamformee_antennas:4 \
- beamformer_antennas:4 \
- rx_antenna_pattern:1 \
- tx_antenna_pattern:1 \
- vht_max_a_mpdu_len_exp:7 \
- vht_max_mpdu:11454 \
- rx_stbc:4 \
- vht_link_adapt:3 \
- vht160:2
-
- set_default tx_burst 2.0
- append base_cfg "ieee80211ac=1" "$N"
- vht_cap=0
- for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
- vht_cap="$(($vht_cap | $cap))"
- done
-
- append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N"
- append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
-
- cap_rx_stbc=$((($vht_cap >> 8) & 7))
- [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
- vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
-
- [ "$vht_oper_chwidth" -lt 2 ] && {
- vht160=0
- short_gi_160=0
- }
-
- mac80211_add_capabilities vht_capab $vht_cap \
- RXLDPC:0x10::$rxldpc \
- SHORT-GI-80:0x20::$short_gi_80 \
- SHORT-GI-160:0x40::$short_gi_160 \
- TX-STBC-2BY1:0x80::$tx_stbc_2by1 \
- SU-BEAMFORMER:0x800::$su_beamformer \
- SU-BEAMFORMEE:0x1000::$su_beamformee \
- MU-BEAMFORMER:0x80000::$mu_beamformer \
- MU-BEAMFORMEE:0x100000::$mu_beamformee \
- VHT-TXOP-PS:0x200000::$vht_txop_ps \
- HTC-VHT:0x400000::$htc_vht \
- RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
- TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
- RX-STBC-1:0x700:0x100:1 \
- RX-STBC-12:0x700:0x200:1 \
- RX-STBC-123:0x700:0x300:1 \
- RX-STBC-1234:0x700:0x400:1 \
-
- [ "$(($vht_cap & 0x800))" -gt 0 -a "$su_beamformer" -gt 0 ] && {
- cap_ant="$(( ( ($vht_cap >> 16) & 3 ) + 1 ))"
- [ "$cap_ant" -gt "$beamformer_antennas" ] && cap_ant="$beamformer_antennas"
- [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[SOUNDING-DIMENSION-$cap_ant]"
- }
-
- [ "$(($vht_cap & 0x1000))" -gt 0 -a "$su_beamformee" -gt 0 ] && {
- cap_ant="$(( ( ($vht_cap >> 13) & 3 ) + 1 ))"
- [ "$cap_ant" -gt "$beamformee_antennas" ] && cap_ant="$beamformee_antennas"
- [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[BF-ANTENNA-$cap_ant]"
- }
-
- # supported Channel widths
- vht160_hw=0
- [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
- vht160_hw=1
- [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
- vht160_hw=2
- [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
- [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
-
- # maximum MPDU length
- vht_max_mpdu_hw=3895
- [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
- vht_max_mpdu_hw=7991
- [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
- vht_max_mpdu_hw=11454
- [ "$vht_max_mpdu_hw" != 3895 ] && \
- vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
-
- # maximum A-MPDU length exponent
- vht_max_a_mpdu_len_exp_hw=0
- [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=1
- [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=2
- [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=3
- [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=4
- [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=5
- [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=6
- [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
- vht_max_a_mpdu_len_exp_hw=7
- vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
-
- # whether or not the STA supports link adaptation using VHT variant
- vht_link_adapt_hw=0
- [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
- vht_link_adapt_hw=2
- [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
- vht_link_adapt_hw=3
- [ "$vht_link_adapt_hw" != 0 ] && \
- vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
-
- [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
- fi
-
- # 802.11ax
- enable_ax=0
- case "$htmode" in
- HE*) enable_ax=1 ;;
- esac
-
- if [ "$enable_ax" != "0" ]; then
- json_get_vars \
- he_su_beamformer:1 \
- he_su_beamformee:1 \
- he_mu_beamformer:1 \
- he_twt_required:0 \
- he_spr_sr_control:3 \
- he_spr_psr_enabled:0 \
- he_spr_non_srg_obss_pd_max_offset:0 \
- he_bss_color:128 \
- he_bss_color_enabled:1
-
- he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1)
- he_phy_cap=${he_phy_cap:2}
- he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1)
- he_mac_cap=${he_mac_cap:2}
-
- append base_cfg "ieee80211ax=1" "$N"
- [ "$hwmode" = "a" ] && {
- append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N"
- append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
- }
-
- mac80211_add_he_capabilities \
- he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \
- he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \
- he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \
- he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \
- he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required
-
- if [ "$he_bss_color_enabled" -gt 0 ]; then
- append base_cfg "he_bss_color=$he_bss_color" "$N"
- [ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \
- append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N"
- he_spr_sr_control=$((he_spr_sr_control | (1 << 2)))
- }
- [ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0)))
- append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N"
- else
- append base_cfg "he_bss_color_disabled=1" "$N"
- fi
-
-
- append base_cfg "he_default_pe_duration=4" "$N"
- append base_cfg "he_rts_threshold=1023" "$N"
- append base_cfg "he_mu_edca_qos_info_param_count=0" "$N"
- append base_cfg "he_mu_edca_qos_info_q_ack=0" "$N"
- append base_cfg "he_mu_edca_qos_info_queue_request=0" "$N"
- append base_cfg "he_mu_edca_qos_info_txop_request=0" "$N"
- append base_cfg "he_mu_edca_ac_be_aifsn=8" "$N"
- append base_cfg "he_mu_edca_ac_be_aci=0" "$N"
- append base_cfg "he_mu_edca_ac_be_ecwmin=9" "$N"
- append base_cfg "he_mu_edca_ac_be_ecwmax=10" "$N"
- append base_cfg "he_mu_edca_ac_be_timer=255" "$N"
- append base_cfg "he_mu_edca_ac_bk_aifsn=15" "$N"
- append base_cfg "he_mu_edca_ac_bk_aci=1" "$N"
- append base_cfg "he_mu_edca_ac_bk_ecwmin=9" "$N"
- append base_cfg "he_mu_edca_ac_bk_ecwmax=10" "$N"
- append base_cfg "he_mu_edca_ac_bk_timer=255" "$N"
- append base_cfg "he_mu_edca_ac_vi_ecwmin=5" "$N"
- append base_cfg "he_mu_edca_ac_vi_ecwmax=7" "$N"
- append base_cfg "he_mu_edca_ac_vi_aifsn=5" "$N"
- append base_cfg "he_mu_edca_ac_vi_aci=2" "$N"
- append base_cfg "he_mu_edca_ac_vi_timer=255" "$N"
- append base_cfg "he_mu_edca_ac_vo_aifsn=5" "$N"
- append base_cfg "he_mu_edca_ac_vo_aci=3" "$N"
- append base_cfg "he_mu_edca_ac_vo_ecwmin=5" "$N"
- append base_cfg "he_mu_edca_ac_vo_ecwmax=7" "$N"
- append base_cfg "he_mu_edca_ac_vo_timer=255" "$N"
- fi
-
- hostapd_prepare_device_config "$hostapd_conf_file" nl80211
- cat >> "$hostapd_conf_file" <<EOF
-${channel:+channel=$channel}
-${channel_list:+chanlist=$channel_list}
-${hostapd_noscan:+noscan=1}
-${tx_burst:+tx_queue_data2_burst=$tx_burst}
-${multiple_bssid:+mbssid=$multiple_bssid}
-#num_global_macaddr=$num_global_macaddr
-$base_cfg
-
-EOF
- json_select ..
-}
-
-mac80211_hostapd_setup_bss() {
- local phy="$1"
- local ifname="$2"
- local macaddr="$3"
- local type="$4"
-
- hostapd_cfg=
- append hostapd_cfg "$type=$ifname" "$N"
-
- hostapd_set_bss_options hostapd_cfg "$phy" "$vif" || return 1
- json_get_vars wds wds_bridge dtim_period max_listen_int start_disabled
-
- set_default wds 0
- set_default start_disabled 0
-
- [ "$wds" -gt 0 ] && {
- append hostapd_cfg "wds_sta=1" "$N"
- [ -n "$wds_bridge" ] && append hostapd_cfg "wds_bridge=$wds_bridge" "$N"
- }
- [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
-
- cat >> /var/run/hostapd-$phy.conf <<EOF
-$hostapd_cfg
-bssid=$macaddr
-${default_macaddr:+#default_macaddr}
-${dtim_period:+dtim_period=$dtim_period}
-${max_listen_int:+max_listen_interval=$max_listen_int}
-EOF
-}
-
-mac80211_get_addr() {
- local phy="$1"
- local idx="$(($2 + 1))"
-
- head -n $idx /sys/class/ieee80211/${phy}/addresses | tail -n1
-}
-
-mac80211_generate_mac() {
- local phy="$1"
- local id="${macidx:-0}"
-
- wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=${multiple_bssid:-0}
-}
-
-get_board_phy_name() (
- local path="$1"
- local fallback_phy=""
-
- __check_phy() {
- local val="$1"
- local key="$2"
- local ref_path="$3"
-
- json_select "$key"
- json_get_vars path
- json_select ..
-
- [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key
- [ "$ref_path" = "$path" ] || return 0
-
- echo "$key"
- exit
- }
-
- json_load_file /etc/board.json
- json_for_each_item __check_phy wlan "$path"
- [ -n "$fallback_phy" ] && echo "${fallback_phy}.${path##*+}"
-)
-
-rename_board_phy_by_path() {
- local path="$1"
-
- local new_phy="$(get_board_phy_name "$path")"
- [ -z "$new_phy" -o "$new_phy" = "$phy" ] && return
-
- iw "$phy" set name "$new_phy" && phy="$new_phy"
-}
-
-rename_board_phy_by_name() (
- local phy="$1"
- local suffix="${phy##*.}"
- [ "$suffix" = "$phy" ] && suffix=
-
- json_load_file /etc/board.json
- json_select wlan
- json_select "${phy%.*}" || return 0
- json_get_vars path
-
- prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")"
- [ -n "$prev_phy" ] || return 0
-
- [ "$prev_phy" = "$phy" ] && return 0
-
- iw "$prev_phy" set name "$phy"
-)
-
-find_phy() {
- [ -n "$phy" ] && {
- rename_board_phy_by_name "$phy"
- [ -d /sys/class/ieee80211/$phy ] && return 0
- }
- [ -n "$path" ] && {
- phy="$(iwinfo nl80211 phyname "path=$path")"
- [ -n "$phy" ] && {
- rename_board_phy_by_path "$path"
- return 0
- }
- }
- [ -n "$macaddr" ] && {
- for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
- grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && {
- path="$(iwinfo nl80211 path "$phy")"
- rename_board_phy_by_path "$path"
- return 0
- }
- done
- }
- return 1
-}
-
-mac80211_check_ap() {
- has_ap=1
-}
-
-mac80211_set_ifname() {
- local phy="$1"
- local prefix="$2"
- eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))"
-}
-
-mac80211_prepare_vif() {
- json_select config
-
- json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file
-
- [ -n "$ifname" ] || {
- local prefix;
-
- case "$mode" in
- ap|sta|mesh) prefix=$mode;;
- adhoc) prefix=ibss;;
- monitor) prefix=mon;;
- esac
-
- mac80211_set_ifname "$phy" "$prefix"
- }
-
- append active_ifnames "$ifname"
- set_default wds 0
- set_default powersave 0
- json_add_string _ifname "$ifname"
-
- default_macaddr=
- if [ -z "$macaddr" ]; then
- macaddr="$(mac80211_generate_mac $phy)"
- macidx="$(($macidx + 1))"
- default_macaddr=1
- elif [ "$macaddr" = 'random' ]; then
- macaddr="$(macaddr_random)"
- fi
- json_add_string _macaddr "$macaddr"
- json_add_string _default_macaddr "$default_macaddr"
- json_select ..
-
-
- [ "$mode" == "ap" ] && {
- [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname"
- [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname"
- }
-
- json_select config
-
- # It is far easier to delete and create the desired interface
- case "$mode" in
- ap)
- # Hostapd will handle recreating the interface and
- # subsequent virtual APs belonging to the same PHY
- if [ -n "$hostapd_ctrl" ]; then
- type=bss
- else
- type=interface
- fi
-
- mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
-
- [ -n "$hostapd_ctrl" ] || {
- ap_ifname="${ifname}"
- hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
- }
- ;;
- esac
-
- json_select ..
-}
-
-mac80211_prepare_iw_htmode() {
- case "$htmode" in
- VHT20|HT20|HE20) iw_htmode=HT20;;
- HT40*|VHT40|VHT160|HE40)
- case "$band" in
- 2g)
- case "$htmode" in
- HT40+) iw_htmode="HT40+";;
- HT40-) iw_htmode="HT40-";;
- *)
- if [ "$channel" -lt 7 ]; then
- iw_htmode="HT40+"
- else
- iw_htmode="HT40-"
- fi
- ;;
- esac
- ;;
- *)
- case "$(( ($channel / 4) % 2 ))" in
- 1) iw_htmode="HT40+" ;;
- 0) iw_htmode="HT40-";;
- esac
- ;;
- esac
- [ "$auto_channel" -gt 0 ] && iw_htmode="HT40+"
- ;;
- VHT80|HE80)
- iw_htmode="80MHZ"
- ;;
- NONE|NOHT)
- iw_htmode="NOHT"
- ;;
- *) iw_htmode="" ;;
- esac
-}
-
-mac80211_add_mesh_params() {
- for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
- eval "mp_val=\"\$$var\""
- [ -n "$mp_val" ] && json_add_string "$var" "$mp_val"
- done
-}
-
-mac80211_setup_adhoc() {
- local enable=$1
- json_get_vars bssid ssid key mcast_rate
-
- NEWUMLIST="${NEWUMLIST}$ifname "
-
- [ "$enable" = 0 ] && {
- ip link set dev "$ifname" down
- return 0
- }
-
- keyspec=
- [ "$auth_type" = "wep" ] && {
- set_default key 1
- case "$key" in
- [1234])
- local idx
- for idx in 1 2 3 4; do
- json_get_var ikey "key$idx"
-
- [ -n "$ikey" ] && {
- ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
- [ $idx -eq $key ] && ikey="d:$ikey"
- append keyspec "$ikey"
- }
- done
- ;;
- *)
- append keyspec "d:0:$(prepare_key_wep "$key")"
- ;;
- esac
- }
-
- brstr=
- for br in $basic_rate_list; do
- wpa_supplicant_add_rate brstr "$br"
- done
-
- mcval=
- [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
-
- local prev
- json_set_namespace wdev_uc prev
-
- json_add_object "$ifname"
- json_add_string mode adhoc
- [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
- json_add_string ssid "$ssid"
- json_add_string freq "$freq"
- json_add_string htmode "$iw_htmode"
- [ -n "$bssid" ] && json_add_string bssid "$bssid"
- json_add_int beacon-interval "$beacon_int"
- [ -n "$brstr" ] && json_add_string basic-rates "$brstr"
- [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
- [ -n "$keyspec" ] && json_add_string keys "$keyspec"
- json_close_object
-
- json_set_namespace "$prev"
-}
-
-mac80211_setup_mesh() {
- json_get_vars ssid mesh_id mcast_rate
-
- mcval=
- [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
- [ -n "$mesh_id" ] && ssid="$mesh_id"
-
- local prev
- json_set_namespace wdev_uc prev
-
- json_add_object "$ifname"
- json_add_string mode mesh
- [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
- json_add_string ssid "$ssid"
- json_add_string freq "$freq"
- json_add_string htmode "$iw_htmode"
- [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
- json_add_int beacon-interval "$beacon_int"
- mac80211_add_mesh_params
-
- json_close_object
-
- json_set_namespace "$prev"
-}
-
-mac80211_setup_monitor() {
- local prev
- json_set_namespace wdev_uc prev
-
- json_add_object "$ifname"
- json_add_string mode monitor
- [ -n "$freq" ] && json_add_string freq "$freq"
- json_add_string htmode "$iw_htmode"
- json_close_object
-
- json_set_namespace "$prev"
-}
-
-mac80211_set_vif_txpower() {
- local name="$1"
-
- json_select config
- json_get_var ifname _ifname
- json_get_vars vif_txpower
- json_select ..
-
- [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
-}
-
-wpa_supplicant_init_config() {
- json_set_namespace wpa_supp prev
-
- json_init
- json_add_array config
-
- json_set_namespace "$prev"
-}
-
-wpa_supplicant_add_interface() {
- local ifname="$1"
- local mode="$2"
- local prev
-
- _wpa_supplicant_common "$ifname"
-
- json_set_namespace wpa_supp prev
-
- json_add_object
- json_add_string ctrl "$_rpath"
- json_add_string iface "$ifname"
- json_add_string mode "$mode"
- json_add_string config "$_config"
- [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
- [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
- [ -n "$wds" ] && json_add_boolean 4addr "$wds"
- json_add_boolean powersave "$powersave"
- [ "$mode" = "mesh" ] && mac80211_add_mesh_params
- json_close_object
-
- json_set_namespace "$prev"
-
- wpa_supp_init=1
-}
-
-wpa_supplicant_set_config() {
- local phy="$1"
- local prev
-
- json_set_namespace wpa_supp prev
- json_close_array
- json_add_string phy "$phy"
- json_add_boolean defer 1
- local data="$(json_dump)"
-
- json_cleanup
- json_set_namespace "$prev"
-
- ubus -S -t 0 wait_for wpa_supplicant || {
- [ -n "$wpa_supp_init" ] || return 0
-
- ubus wait_for wpa_supplicant
- }
-
- local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")"
- ret="$?"
- [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
-
- wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
-
-}
-
-hostapd_set_config() {
- [ -n "$hostapd_ctrl" ] || {
- ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
- return 0;
- }
-
- ubus wait_for hostapd
- local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
- ret="$?"
- [ "$ret" != 0 -o -z "$hostapd_res" ] && {
- wireless_setup_failed HOSTAPD_START_FAILED
- return
- }
- wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1
-}
-
-
-wpa_supplicant_start() {
- local phy="$1"
-
- [ -n "$wpa_supp_init" ] || return 0
-
- ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
-}
-
-mac80211_setup_supplicant() {
- local enable=$1
- local add_sp=0
-
- wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
-
- if [ "$mode" = "sta" ]; then
- wpa_supplicant_add_network "$ifname"
- else
- wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$hostapd_noscan"
- fi
-
- wpa_supplicant_add_interface "$ifname" "$mode"
-
- return 0
-}
-
-mac80211_setup_vif() {
- local name="$1"
- local failed
-
- json_select config
- json_get_var ifname _ifname
- json_get_var macaddr _macaddr
- json_get_var default_macaddr _default_macaddr
- json_get_vars mode wds powersave
-
- set_default powersave 0
- set_default wds 0
-
- case "$mode" in
- mesh)
- json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING
- wireless_vif_parse_encryption
- [ -z "$htmode" ] && htmode="NOHT";
- if wpa_supplicant -vmesh; then
- mac80211_setup_supplicant || failed=1
- else
- mac80211_setup_mesh
- fi
- ;;
- adhoc)
- wireless_vif_parse_encryption
- if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
- mac80211_setup_supplicant || failed=1
- else
- mac80211_setup_adhoc
- fi
- ;;
- sta)
- mac80211_setup_supplicant || failed=1
- ;;
- monitor)
- mac80211_setup_monitor
- ;;
- esac
-
- json_select ..
- [ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
-}
-
-get_freq() {
- local phy="$1"
- local channel="$2"
- local band="$3"
-
- case "$band" in
- 2g) band="1:";;
- 5g) band="2:";;
- 60g) band="3:";;
- 6g) band="4:";;
- esac
-
- iw "$phy" info | awk -v band="$band" -v channel="[$channel]" '
-
-$1 ~ /Band/ {
- band_match = band == $2
-}
-
-band_match && $3 == "MHz" && $4 == channel {
- print $2
- exit
-}
-'
-}
-
-chan_is_dfs() {
- local phy="$1"
- local chan="$2"
- iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection"
- return $!
-}
-
-mac80211_set_noscan() {
- hostapd_noscan=1
-}
-
-drv_mac80211_cleanup() {
- :
-}
-
-mac80211_reset_config() {
- local phy="$1"
-
- hostapd_conf_file="/var/run/hostapd-$phy.conf"
- ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
- ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
- wdev_tool "$phy" set_config '{}'
-}
-
-drv_mac80211_setup() {
- json_select config
- json_get_vars \
- phy macaddr path \
- country chanbw distance \
- txpower \
- rxantenna txantenna \
- frag rts beacon_int:100 htmode \
- num_global_macaddr:1 multiple_bssid
- json_get_values basic_rate_list basic_rate
- json_get_values scan_list scan_list
- json_select ..
-
- json_select data && {
- json_get_var prev_rxantenna rxantenna
- json_get_var prev_txantenna txantenna
- json_select ..
- }
-
- find_phy || {
- echo "Could not find PHY for device '$1'"
- wireless_set_retry 0
- return 1
- }
-
- local wdev
- local cwdev
- local found
-
- # convert channel to frequency
- [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")"
-
- [ -n "$country" ] && {
- iw reg get | grep -q "^country $country:" || {
- iw reg set "$country"
- sleep 1
- }
- }
-
- hostapd_conf_file="/var/run/hostapd-$phy.conf"
-
- macidx=0
- staidx=0
-
- [ -n "$chanbw" ] && {
- for file in /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
- [ -f "$file" ] && echo "$chanbw" > "$file"
- done
- }
-
- set_default rxantenna 0xffffffff
- set_default txantenna 0xffffffff
- set_default distance 0
-
- [ "$txantenna" = "all" ] && txantenna=0xffffffff
- [ "$rxantenna" = "all" ] && rxantenna=0xffffffff
-
- [ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy"
- wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna"
-
- iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
- iw phy "$phy" set distance "$distance" >/dev/null 2>&1
-
- if [ -n "$txpower" ]; then
- iw phy "$phy" set txpower fixed "${txpower%%.*}00"
- else
- iw phy "$phy" set txpower auto
- fi
-
- [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
- [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
-
- has_ap=
- hostapd_ctrl=
- ap_ifname=
- hostapd_noscan=
- wpa_supp_init=
- for_each_interface "ap" mac80211_check_ap
-
- [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev"
-
- for_each_interface "sta adhoc mesh" mac80211_set_noscan
- [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
-
- local prev
- json_set_namespace wdev_uc prev
- json_init
- json_set_namespace "$prev"
-
- wpa_supplicant_init_config
-
- mac80211_prepare_iw_htmode
- active_ifnames=
- for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
- for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
-
- [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
- [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
-
- [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
-
- json_set_namespace wdev_uc prev
- wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
- json_set_namespace "$prev"
-
- for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
- wireless_set_up
-}
-
-_list_phy_interfaces() {
- local phy="$1"
- if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
- ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
- else
- ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
- fi
-}
-
-list_phy_interfaces() {
- local phy="$1"
-
- for dev in $(_list_phy_interfaces "$phy"); do
- readlink "/sys/class/net/${dev}/phy80211" | grep -q "/${phy}\$" || continue
- echo "$dev"
- done
-}
-
-drv_mac80211_teardown() {
- json_select data
- json_get_vars phy
- json_select ..
- [ -n "$phy" ] || {
- echo "Bug: PHY is undefined for device '$1'"
- return 1
- }
-
- mac80211_reset_config "$phy"
-
- for wdev in $(list_phy_interfaces "$phy"); do
- ip link set dev "$wdev" down
- iw dev "$wdev" del
- done
-}
-
-add_driver mac80211
+++ /dev/null
-#!/bin/sh
-
-append DRIVERS "mac80211"
-
-check_mac80211_device() {
- local device="$1"
- local path="$2"
- local macaddr="$3"
-
- [ -n "$found" ] && return 0
-
- phy_path=
- config_get phy "$device" phy
- json_select wlan
- [ -n "$phy" ] && case "$phy" in
- phy*)
- [ -d /sys/class/ieee80211/$phy ] && \
- phy_path="$(iwinfo nl80211 path "$dev")"
- ;;
- *)
- if json_is_a "$phy" object; then
- json_select "$phy"
- json_get_var phy_path path
- json_select ..
- elif json_is_a "${phy%.*}" object; then
- json_select "${phy%.*}"
- json_get_var phy_path path
- json_select ..
- phy_path="$phy_path+${phy##*.}"
- fi
- ;;
- esac
- json_select ..
- [ -n "$phy_path" ] || config_get phy_path "$device" path
- [ -n "$path" -a "$phy_path" = "$path" ] && {
- found=1
- return 0
- }
-
- config_get dev_macaddr "$device" macaddr
-
- [ -n "$macaddr" -a "$dev_macaddr" = "$macaddr" ] && found=1
-
- return 0
-}
-
-
-__get_band_defaults() {
- local phy="$1"
-
- ( iw phy "$phy" info; echo ) | awk '
-BEGIN {
- bands = ""
-}
-
-($1 == "Band" || $1 == "") && band {
- if (channel) {
- mode="NOHT"
- if (ht) mode="HT20"
- if (vht && band != "1:") mode="VHT80"
- if (he) mode="HE80"
- if (he && band == "1:") mode="HE20"
- sub("\\[", "", channel)
- sub("\\]", "", channel)
- bands = bands band channel ":" mode " "
- }
- band=""
-}
-
-$1 == "Band" {
- band = $2
- channel = ""
- vht = ""
- ht = ""
- he = ""
-}
-
-$0 ~ "Capabilities:" {
- ht=1
-}
-
-$0 ~ "VHT Capabilities" {
- vht=1
-}
-
-$0 ~ "HE Iftypes" {
- he=1
-}
-
-$1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel {
- channel = $4
-}
-
-END {
- print bands
-}'
-}
-
-get_band_defaults() {
- local phy="$1"
-
- for c in $(__get_band_defaults "$phy"); do
- local band="${c%%:*}"
- c="${c#*:}"
- local chan="${c%%:*}"
- c="${c#*:}"
- local mode="${c%%:*}"
-
- case "$band" in
- 1) band=2g;;
- 2) band=5g;;
- 3) band=60g;;
- 4) band=6g;;
- *) band="";;
- esac
-
- [ -n "$band" ] || continue
- [ -n "$mode_band" -a "$band" = "6g" ] && return
-
- mode_band="$band"
- channel="$chan"
- htmode="$mode"
- done
-}
-
-check_devidx() {
- case "$1" in
- radio[0-9]*)
- local idx="${1#radio}"
- [ "$devidx" -ge "${1#radio}" ] && devidx=$((idx + 1))
- ;;
- esac
-}
-
-check_board_phy() {
- local name="$2"
-
- json_select "$name"
- json_get_var phy_path path
- json_select ..
-
- if [ "$path" = "$phy_path" ]; then
- board_dev="$name"
- elif [ "${path%+*}" = "$phy_path" ]; then
- fallback_board_dev="$name.${path#*+}"
- fi
-}
-
-detect_mac80211() {
- devidx=0
- config_load wireless
- config_foreach check_devidx wifi-device
-
- json_load_file /etc/board.json
-
- for _dev in /sys/class/ieee80211/*; do
- [ -e "$_dev" ] || continue
-
- dev="${_dev##*/}"
-
- mode_band=""
- channel=""
- htmode=""
- ht_capab=""
-
- get_band_defaults "$dev"
-
- path="$(iwinfo nl80211 path "$dev")"
- macaddr="$(cat /sys/class/ieee80211/${dev}/macaddress)"
-
- # work around phy rename related race condition
- [ -n "$path" -o -n "$macaddr" ] || continue
-
- board_dev=
- fallback_board_dev=
- json_for_each_item check_board_phy wlan
- [ -n "$board_dev" ] || board_dev="$fallback_board_dev"
- [ -n "$board_dev" ] && dev="$board_dev"
-
- found=
- config_foreach check_mac80211_device wifi-device "$path" "$macaddr"
- [ -n "$found" ] && continue
-
- name="radio${devidx}"
- devidx=$(($devidx + 1))
- case "$dev" in
- phy*)
- if [ -n "$path" ]; then
- dev_id="set wireless.${name}.path='$path'"
- else
- dev_id="set wireless.${name}.macaddr='$macaddr'"
- fi
- ;;
- *)
- dev_id="set wireless.${name}.phy='$dev'"
- ;;
- esac
-
- uci -q batch <<-EOF
- set wireless.${name}=wifi-device
- set wireless.${name}.type=mac80211
- ${dev_id}
- set wireless.${name}.channel=${channel}
- set wireless.${name}.band=${mode_band}
- set wireless.${name}.htmode=$htmode
- set wireless.${name}.disabled=1
-
- set wireless.default_${name}=wifi-iface
- set wireless.default_${name}.device=${name}
- set wireless.default_${name}.network=lan
- set wireless.default_${name}.mode=ap
- set wireless.default_${name}.ssid=OpenWrt
- set wireless.default_${name}.encryption=none
-EOF
- uci -q commit wireless
- done
-}
+++ /dev/null
-#!/bin/sh
-
-[ "${ACTION}" = "add" ] && {
- /sbin/wifi config
-}
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
- $(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/
+ $(CP) \
+ $(PKG_BUILD_DIR)/scripts/utils.sh \
+ $(PKG_BUILD_DIR)/scripts/netifd-proto.sh \
+ $(1)/lib/netifd/
endef
$(eval $(call BuildPackage,netifd))
--- /dev/null
+#
+# Copyright (C) 2024 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wifi-scripts
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+PKG_LICENSE:=GPL-2.0
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/wifi-scripts
+ SECTION:=utils
+ CATEGORY:=Base system
+ DEPENDS:=+netifd +ucode +ucode-mod-nl80211 +ucode-mod-ubus
+ TITLE:=Wi-Fi configuration scripts
+ PKGARCH:=all
+endef
+
+define Package/qos-scripts/description
+ A set of scripts that handle setup and configuration of Wi-Fi devices.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/wifi-scripts/install
+ $(INSTALL_DIR) $(1)
+ $(CP) ./files/* $(1)/
+endef
+
+$(eval $(call BuildPackage,wifi-scripts))
--- /dev/null
+#!/bin/sh
+
+[ "${ACTION}" = "add" ] && {
+ /sbin/wifi config
+}
--- /dev/null
+. /lib/functions/network.sh
+. /lib/functions.sh
+
+wpa_supplicant_add_rate() {
+ local var="$1"
+ local val="$(($2 / 1000))"
+ local sub="$((($2 / 100) % 10))"
+ append $var "$val" ","
+ [ $sub -gt 0 ] && append $var "."
+}
+
+hostapd_add_rate() {
+ local var="$1"
+ local val="$(($2 / 100))"
+ append $var "$val" " "
+}
+
+hostapd_append_wep_key() {
+ local var="$1"
+
+ wep_keyidx=0
+ set_default key 1
+ case "$key" in
+ [1234])
+ for idx in 1 2 3 4; do
+ local zidx
+ zidx="$(($idx - 1))"
+ json_get_var ckey "key${idx}"
+ [ -n "$ckey" ] && \
+ append $var "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N$T"
+ done
+ wep_keyidx="$((key - 1))"
+ ;;
+ *)
+ append $var "wep_key0=$(prepare_key_wep "$key")" "$N$T"
+ ;;
+ esac
+}
+
+hostapd_append_wpa_key_mgmt() {
+ local auth_type_l="$(echo $auth_type | tr 'a-z' 'A-Z')"
+
+ case "$auth_type" in
+ psk|eap)
+ append wpa_key_mgmt "WPA-$auth_type_l"
+ [ "${wpa:-2}" -ge 2 ] && [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}"
+ [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-${auth_type_l}-SHA256"
+ ;;
+ eap192)
+ append wpa_key_mgmt "WPA-EAP-SUITE-B-192"
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP-SHA384"
+ ;;
+ eap-eap2)
+ append wpa_key_mgmt "WPA-EAP"
+ append wpa_key_mgmt "WPA-EAP-SHA256"
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
+ ;;
+ eap2)
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
+ append wpa_key_mgmt "WPA-EAP-SHA256"
+ ;;
+ sae)
+ append wpa_key_mgmt "SAE"
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
+ ;;
+ psk-sae)
+ append wpa_key_mgmt "WPA-PSK"
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-PSK"
+ [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-PSK-SHA256"
+ append wpa_key_mgmt "SAE"
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
+ ;;
+ owe)
+ append wpa_key_mgmt "OWE"
+ ;;
+ esac
+
+ [ "$fils" -gt 0 ] && {
+ case "$auth_type" in
+ eap-192)
+ append wpa_key_mgmt FILS-SHA384
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA384
+ ;;
+ eap*)
+ append wpa_key_mgmt FILS-SHA256
+ [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA256
+ ;;
+ esac
+ }
+
+ [ "$auth_osen" = "1" ] && append wpa_key_mgmt "OSEN"
+}
+
+hostapd_add_log_config() {
+ config_add_boolean \
+ log_80211 \
+ log_8021x \
+ log_radius \
+ log_wpa \
+ log_driver \
+ log_iapp \
+ log_mlme
+
+ config_add_int log_level
+}
+
+hostapd_common_add_device_config() {
+ config_add_array basic_rate
+ config_add_array supported_rates
+ config_add_string beacon_rate
+
+ config_add_string country country3
+ config_add_boolean country_ie doth
+ config_add_boolean spectrum_mgmt_required
+ config_add_int local_pwr_constraint
+ config_add_string require_mode
+ config_add_boolean legacy_rates
+ config_add_int cell_density
+ config_add_int rts_threshold
+ config_add_int rssi_reject_assoc_rssi
+ config_add_int rssi_ignore_probe_request
+ config_add_int maxassoc
+
+ config_add_string acs_chan_bias
+ config_add_array hostapd_options
+
+ config_add_int airtime_mode
+ config_add_int mbssid
+
+ hostapd_add_log_config
+}
+
+hostapd_prepare_device_config() {
+ local config="$1"
+ local driver="$2"
+
+ local base_cfg=
+
+ json_get_vars country country3 country_ie beacon_int:100 doth require_mode legacy_rates \
+ acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \
+ rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc \
+ mbssid:0
+
+ hostapd_set_log_options base_cfg
+
+ set_default country_ie 1
+ set_default spectrum_mgmt_required 0
+ set_default doth 1
+ set_default legacy_rates 0
+ set_default airtime_mode 0
+ set_default cell_density 0
+
+ [ -n "$country" ] && {
+ append base_cfg "country_code=$country" "$N"
+ [ -n "$country3" ] && append base_cfg "country3=$country3" "$N"
+
+ [ "$country_ie" -gt 0 ] && {
+ append base_cfg "ieee80211d=1" "$N"
+ [ -n "$local_pwr_constraint" ] && append base_cfg "local_pwr_constraint=$local_pwr_constraint" "$N"
+ [ "$spectrum_mgmt_required" -gt 0 ] && append base_cfg "spectrum_mgmt_required=$spectrum_mgmt_required" "$N"
+ }
+ [ "$hwmode" = "a" -a "$doth" -gt 0 ] && append base_cfg "ieee80211h=1" "$N"
+ }
+
+ [ -n "$acs_chan_bias" ] && append base_cfg "acs_chan_bias=$acs_chan_bias" "$N"
+
+ local brlist= br
+ json_get_values basic_rate_list basic_rate
+ local rlist= r
+ json_get_values rate_list supported_rates
+
+ [ -n "$hwmode" ] && append base_cfg "hw_mode=$hwmode" "$N"
+ if [ "$hwmode" = "g" ] || [ "$hwmode" = "a" ]; then
+ [ -n "$require_mode" ] && legacy_rates=0
+ case "$require_mode" in
+ n) append base_cfg "require_ht=1" "$N";;
+ ac) append base_cfg "require_vht=1" "$N";;
+ esac
+ fi
+ case "$hwmode" in
+ b)
+ if [ "$cell_density" -eq 1 ]; then
+ set_default rate_list "5500 11000"
+ set_default basic_rate_list "5500 11000"
+ elif [ "$cell_density" -ge 2 ]; then
+ set_default rate_list "11000"
+ set_default basic_rate_list "11000"
+ fi
+ ;;
+ g)
+ if [ "$cell_density" -eq 0 ] || [ "$cell_density" -eq 1 ]; then
+ if [ "$legacy_rates" -eq 0 ]; then
+ set_default rate_list "6000 9000 12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "6000 12000 24000"
+ elif [ "$cell_density" -eq 1 ]; then
+ set_default rate_list "5500 6000 9000 11000 12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "5500 11000"
+ fi
+ elif [ "$cell_density" -ge 3 ] && [ "$legacy_rates" -ne 0 ] || [ "$cell_density" -eq 2 ]; then
+ if [ "$legacy_rates" -eq 0 ]; then
+ set_default rate_list "12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "12000 24000"
+ else
+ set_default rate_list "11000 12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "11000"
+ fi
+ elif [ "$cell_density" -ge 3 ]; then
+ set_default rate_list "24000 36000 48000 54000"
+ set_default basic_rate_list "24000"
+ fi
+ ;;
+ a)
+ if [ "$cell_density" -eq 1 ]; then
+ set_default rate_list "6000 9000 12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "6000 12000 24000"
+ elif [ "$cell_density" -eq 2 ]; then
+ set_default rate_list "12000 18000 24000 36000 48000 54000"
+ set_default basic_rate_list "12000 24000"
+ elif [ "$cell_density" -ge 3 ]; then
+ set_default rate_list "24000 36000 48000 54000"
+ set_default basic_rate_list "24000"
+ fi
+ ;;
+ esac
+
+ for r in $rate_list; do
+ hostapd_add_rate rlist "$r"
+ done
+
+ for br in $basic_rate_list; do
+ hostapd_add_rate brlist "$br"
+ done
+
+ [ -n "$rssi_reject_assoc_rssi" ] && append base_cfg "rssi_reject_assoc_rssi=$rssi_reject_assoc_rssi" "$N"
+ [ -n "$rssi_ignore_probe_request" ] && append base_cfg "rssi_ignore_probe_request=$rssi_ignore_probe_request" "$N"
+ [ -n "$beacon_rate" ] && append base_cfg "beacon_rate=$beacon_rate" "$N"
+ [ -n "$rlist" ] && append base_cfg "supported_rates=$rlist" "$N"
+ [ -n "$brlist" ] && append base_cfg "basic_rates=$brlist" "$N"
+ append base_cfg "beacon_int=$beacon_int" "$N"
+ [ -n "$rts_threshold" ] && append base_cfg "rts_threshold=$rts_threshold" "$N"
+ [ "$airtime_mode" -gt 0 ] && append base_cfg "airtime_mode=$airtime_mode" "$N"
+ [ -n "$maxassoc" ] && append base_cfg "iface_max_num_sta=$maxassoc" "$N"
+ [ "$mbssid" -gt 0 ] && [ "$mbssid" -le 2 ] && append base_cfg "mbssid=$mbssid" "$N"
+
+ json_get_values opts hostapd_options
+ for val in $opts; do
+ append base_cfg "$val" "$N"
+ done
+
+ cat > "$config" <<EOF
+driver=$driver
+$base_cfg
+EOF
+}
+
+hostapd_common_add_bss_config() {
+ config_add_string 'bssid:macaddr' 'ssid:string'
+ config_add_boolean wds wmm uapsd hidden utf8_ssid ppsk
+
+ config_add_int maxassoc max_inactivity
+ config_add_boolean disassoc_low_ack isolate short_preamble skip_inactivity_poll
+
+ config_add_int \
+ wep_rekey eap_reauth_period \
+ wpa_group_rekey wpa_pair_rekey wpa_master_rekey
+ config_add_boolean wpa_strict_rekey
+ config_add_boolean wpa_disable_eapol_key_retries
+
+ config_add_boolean tdls_prohibit
+
+ config_add_boolean rsn_preauth auth_cache
+ config_add_int ieee80211w
+ config_add_int eapol_version
+
+ config_add_array auth_server acct_server
+ config_add_string 'server:host'
+ config_add_string auth_secret key
+ config_add_int 'auth_port:port' 'port:port'
+
+ config_add_string acct_secret
+ config_add_int acct_port
+ config_add_int acct_interval
+
+ config_add_int bss_load_update_period chan_util_avg_period
+
+ config_add_string dae_client
+ config_add_string dae_secret
+ config_add_int dae_port
+
+ config_add_string nasid
+ config_add_string ownip
+ config_add_string radius_client_addr
+ config_add_string iapp_interface
+ config_add_string eap_type ca_cert client_cert identity anonymous_identity auth priv_key priv_key_pwd
+ config_add_boolean ca_cert_usesystem ca_cert2_usesystem
+ config_add_string subject_match subject_match2
+ config_add_array altsubject_match altsubject_match2
+ config_add_array domain_match domain_match2 domain_suffix_match domain_suffix_match2
+ config_add_string ieee80211w_mgmt_cipher
+
+ config_add_int dynamic_vlan vlan_naming vlan_no_bridge
+ config_add_string vlan_tagged_interface vlan_bridge
+ config_add_string vlan_file
+
+ config_add_string 'key1:wepkey' 'key2:wepkey' 'key3:wepkey' 'key4:wepkey' 'password:wpakey'
+
+ config_add_string wpa_psk_file
+
+ config_add_int multi_ap
+
+ config_add_boolean wps_pushbutton wps_label ext_registrar wps_pbc_in_m1
+ config_add_int wps_ap_setup_locked wps_independent
+ config_add_string wps_device_type wps_device_name wps_manufacturer wps_pin
+ config_add_string multi_ap_backhaul_ssid multi_ap_backhaul_key
+
+ config_add_boolean wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo
+ config_add_int time_advertisement
+ config_add_string time_zone
+ config_add_string vendor_elements
+
+ config_add_boolean ieee80211k rrm_neighbor_report rrm_beacon_report
+
+ config_add_boolean ftm_responder stationary_ap
+ config_add_string lci civic
+
+ config_add_boolean ieee80211r pmk_r1_push ft_psk_generate_local ft_over_ds
+ config_add_int r0_key_lifetime reassociation_deadline
+ config_add_string mobility_domain r1_key_holder
+ config_add_array r0kh r1kh
+
+ config_add_int ieee80211w_max_timeout ieee80211w_retry_timeout
+
+ config_add_string macfilter 'macfile:file'
+ config_add_array 'maclist:list(macaddr)'
+
+ config_add_array bssid_blacklist
+ config_add_array bssid_whitelist
+
+ config_add_int mcast_rate
+ config_add_array basic_rate
+ config_add_array supported_rates
+
+ config_add_boolean sae_require_mfp
+ config_add_int sae_pwe
+
+ config_add_string 'owe_transition_bssid:macaddr' 'owe_transition_ssid:string'
+ config_add_string owe_transition_ifname
+
+ config_add_boolean iw_enabled iw_internet iw_asra iw_esr iw_uesa
+ config_add_int iw_access_network_type iw_venue_group iw_venue_type
+ config_add_int iw_ipaddr_type_availability iw_gas_address3
+ config_add_string iw_hessid iw_network_auth_type iw_qos_map_set
+ config_add_array iw_roaming_consortium iw_domain_name iw_anqp_3gpp_cell_net iw_nai_realm
+ config_add_array iw_anqp_elem iw_venue_name iw_venue_url
+
+ config_add_boolean hs20 disable_dgaf osen
+ config_add_int anqp_domain_id
+ config_add_int hs20_deauth_req_timeout
+ config_add_array hs20_oper_friendly_name
+ config_add_array osu_provider
+ config_add_array operator_icon
+ config_add_array hs20_conn_capab
+ config_add_string osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp
+
+ config_add_string hs20_t_c_server_url
+
+ config_add_array airtime_sta_weight
+ config_add_int airtime_bss_weight airtime_bss_limit
+
+ config_add_boolean multicast_to_unicast multicast_to_unicast_all proxy_arp per_sta_vif
+
+ config_add_array hostapd_bss_options
+ config_add_boolean default_disabled
+
+ config_add_boolean request_cui
+ config_add_array radius_auth_req_attr
+ config_add_array radius_acct_req_attr
+
+ config_add_int eap_server
+ config_add_string eap_user_file ca_cert server_cert private_key private_key_passwd server_id
+
+ config_add_boolean fils
+ config_add_string fils_dhcp
+
+ config_add_int ocv
+}
+
+hostapd_set_vlan_file() {
+ local ifname="$1"
+ local vlan="$2"
+ json_get_vars name vid
+ echo "${vid} ${ifname}-${name}" >> /var/run/hostapd-${ifname}.vlan
+ wireless_add_vlan "${vlan}" "${ifname}-${name}"
+}
+
+hostapd_set_vlan() {
+ local ifname="$1"
+
+ rm -f /var/run/hostapd-${ifname}.vlan
+ for_each_vlan hostapd_set_vlan_file ${ifname}
+}
+
+hostapd_set_psk_file() {
+ local ifname="$1"
+ local vlan="$2"
+ local vlan_id=""
+
+ json_get_vars mac vid key
+ set_default mac "00:00:00:00:00:00"
+ [ -n "$vid" ] && vlan_id="vlanid=$vid "
+ echo "${vlan_id} ${mac} ${key}" >> /var/run/hostapd-${ifname}.psk
+}
+
+hostapd_set_psk() {
+ local ifname="$1"
+
+ rm -f /var/run/hostapd-${ifname}.psk
+ for_each_station hostapd_set_psk_file ${ifname}
+}
+
+append_iw_roaming_consortium() {
+ [ -n "$1" ] && append bss_conf "roaming_consortium=$1" "$N"
+}
+
+append_iw_domain_name() {
+ if [ -z "$iw_domain_name_conf" ]; then
+ iw_domain_name_conf="$1"
+ else
+ iw_domain_name_conf="$iw_domain_name_conf,$1"
+ fi
+}
+
+append_iw_anqp_3gpp_cell_net() {
+ if [ -z "$iw_anqp_3gpp_cell_net_conf" ]; then
+ iw_anqp_3gpp_cell_net_conf="$1"
+ else
+ iw_anqp_3gpp_cell_net_conf="$iw_anqp_3gpp_cell_net_conf:$1"
+ fi
+}
+
+append_iw_anqp_elem() {
+ [ -n "$1" ] && append bss_conf "anqp_elem=$1" "$N"
+}
+
+append_iw_nai_realm() {
+ [ -n "$1" ] && append bss_conf "nai_realm=$1" "$N"
+}
+
+append_iw_venue_name() {
+ append bss_conf "venue_name=$1" "$N"
+}
+
+append_iw_venue_url() {
+ append bss_conf "venue_url=$1" "$N"
+}
+
+append_hs20_oper_friendly_name() {
+ append bss_conf "hs20_oper_friendly_name=$1" "$N"
+}
+
+append_osu_provider_friendly_name() {
+ append bss_conf "osu_friendly_name=$1" "$N"
+}
+
+append_osu_provider_service_desc() {
+ append bss_conf "osu_service_desc=$1" "$N"
+}
+
+append_hs20_icon() {
+ local width height lang type path
+ config_get width "$1" width
+ config_get height "$1" height
+ config_get lang "$1" lang
+ config_get type "$1" type
+ config_get path "$1" path
+
+ append bss_conf "hs20_icon=$width:$height:$lang:$type:$1:$path" "$N"
+}
+
+append_hs20_icons() {
+ config_load wireless
+ config_foreach append_hs20_icon hs20-icon
+}
+
+append_operator_icon() {
+ append bss_conf "operator_icon=$1" "$N"
+}
+
+append_osu_icon() {
+ append bss_conf "osu_icon=$1" "$N"
+}
+
+append_osu_provider() {
+ local cfgtype osu_server_uri osu_friendly_name osu_nai osu_nai2 osu_method_list
+
+ config_load wireless
+ config_get cfgtype "$1" TYPE
+ [ "$cfgtype" != "osu-provider" ] && return
+
+ append bss_conf "# provider $1" "$N"
+ config_get osu_server_uri "$1" osu_server_uri
+ config_get osu_nai "$1" osu_nai
+ config_get osu_nai2 "$1" osu_nai2
+ config_get osu_method_list "$1" osu_method
+
+ append bss_conf "osu_server_uri=$osu_server_uri" "$N"
+ append bss_conf "osu_nai=$osu_nai" "$N"
+ append bss_conf "osu_nai2=$osu_nai2" "$N"
+ append bss_conf "osu_method_list=$osu_method_list" "$N"
+
+ config_list_foreach "$1" osu_service_desc append_osu_provider_service_desc
+ config_list_foreach "$1" osu_friendly_name append_osu_friendly_name
+ config_list_foreach "$1" osu_icon append_osu_icon
+
+ append bss_conf "$N"
+}
+
+append_hs20_conn_capab() {
+ [ -n "$1" ] && append bss_conf "hs20_conn_capab=$1" "$N"
+}
+
+append_radius_acct_req_attr() {
+ [ -n "$1" ] && append bss_conf "radius_acct_req_attr=$1" "$N"
+}
+
+append_radius_auth_req_attr() {
+ [ -n "$1" ] && append bss_conf "radius_auth_req_attr=$1" "$N"
+}
+
+append_airtime_sta_weight() {
+ [ -n "$1" ] && append bss_conf "airtime_sta_weight=$1" "$N"
+}
+
+append_auth_server() {
+ [ -n "$1" ] || return
+ append bss_conf "auth_server_addr=$1" "$N"
+ append bss_conf "auth_server_port=$auth_port" "$N"
+ [ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+}
+
+append_acct_server() {
+ [ -n "$1" ] || return
+ append bss_conf "acct_server_addr=$1" "$N"
+ append bss_conf "acct_server_port=$acct_port" "$N"
+ [ -n "$acct_secret" ] && append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
+}
+
+hostapd_set_bss_options() {
+ local var="$1"
+ local phy="$2"
+ local vif="$3"
+
+ wireless_vif_parse_encryption
+
+ local bss_conf bss_md5sum ft_key
+ local wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wpa_key_mgmt
+
+ json_get_vars \
+ wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wpa_strict_rekey \
+ wpa_disable_eapol_key_retries tdls_prohibit \
+ maxassoc max_inactivity disassoc_low_ack isolate auth_cache \
+ wps_pushbutton wps_label ext_registrar wps_pbc_in_m1 wps_ap_setup_locked \
+ wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \
+ macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
+ iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
+ acct_secret acct_port acct_interval \
+ bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \
+ multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \
+ ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \
+ multicast_to_unicast_all proxy_arp per_sta_vif \
+ eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id \
+ vendor_elements fils ocv
+
+ set_default fils 0
+ set_default isolate 0
+ set_default maxassoc 0
+ set_default max_inactivity 0
+ set_default short_preamble 1
+ set_default disassoc_low_ack 1
+ set_default skip_inactivity_poll 0
+ set_default hidden 0
+ set_default wmm 1
+ set_default uapsd 1
+ set_default wpa_disable_eapol_key_retries 0
+ set_default tdls_prohibit 0
+ set_default eapol_version $((wpa & 1))
+ set_default acct_port 1813
+ set_default bss_load_update_period 60
+ set_default chan_util_avg_period 600
+ set_default utf8_ssid 1
+ set_default multi_ap 0
+ set_default ppsk 0
+ set_default airtime_bss_weight 0
+ set_default airtime_bss_limit 0
+ set_default eap_server 0
+
+ /usr/sbin/hostapd -vfils || fils=0
+
+ append bss_conf "ctrl_interface=/var/run/hostapd"
+ if [ "$isolate" -gt 0 ]; then
+ append bss_conf "ap_isolate=$isolate" "$N"
+ fi
+ if [ "$maxassoc" -gt 0 ]; then
+ append bss_conf "max_num_sta=$maxassoc" "$N"
+ fi
+ if [ "$max_inactivity" -gt 0 ]; then
+ append bss_conf "ap_max_inactivity=$max_inactivity" "$N"
+ fi
+
+ [ "$airtime_bss_weight" -gt 0 ] && append bss_conf "airtime_bss_weight=$airtime_bss_weight" "$N"
+ [ "$airtime_bss_limit" -gt 0 ] && append bss_conf "airtime_bss_limit=$airtime_bss_limit" "$N"
+ json_for_each_item append_airtime_sta_weight airtime_sta_weight
+
+ append bss_conf "bss_load_update_period=$bss_load_update_period" "$N"
+ append bss_conf "chan_util_avg_period=$chan_util_avg_period" "$N"
+ append bss_conf "disassoc_low_ack=$disassoc_low_ack" "$N"
+ append bss_conf "skip_inactivity_poll=$skip_inactivity_poll" "$N"
+ append bss_conf "preamble=$short_preamble" "$N"
+ append bss_conf "wmm_enabled=$wmm" "$N"
+ append bss_conf "ignore_broadcast_ssid=$hidden" "$N"
+ append bss_conf "uapsd_advertisement_enabled=$uapsd" "$N"
+ append bss_conf "utf8_ssid=$utf8_ssid" "$N"
+ append bss_conf "multi_ap=$multi_ap" "$N"
+ [ -n "$vendor_elements" ] && append bss_conf "vendor_elements=$vendor_elements" "$N"
+
+ [ "$tdls_prohibit" -gt 0 ] && append bss_conf "tdls_prohibit=$tdls_prohibit" "$N"
+
+ [ "$wpa" -gt 0 ] && {
+ [ -n "$wpa_group_rekey" ] && append bss_conf "wpa_group_rekey=$wpa_group_rekey" "$N"
+ [ -n "$wpa_pair_rekey" ] && append bss_conf "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
+ [ -n "$wpa_master_rekey" ] && append bss_conf "wpa_gmk_rekey=$wpa_master_rekey" "$N"
+ [ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
+ }
+
+ [ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
+
+ [ -n "$acct_interval" ] && \
+ append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
+ json_for_each_item append_acct_server acct_server
+ json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
+
+ [ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N"
+
+ case "$auth_type" in
+ sae|owe|eap2|eap192)
+ set_default ieee80211w 2
+ set_default sae_require_mfp 1
+ set_default sae_pwe 2
+ ;;
+ psk-sae|eap-eap2)
+ set_default ieee80211w 1
+ set_default sae_require_mfp 1
+ set_default sae_pwe 2
+ ;;
+ esac
+ [ -n "$sae_require_mfp" ] && append bss_conf "sae_require_mfp=$sae_require_mfp" "$N"
+ [ -n "$sae_pwe" ] && append bss_conf "sae_pwe=$sae_pwe" "$N"
+
+ local vlan_possible=""
+
+ case "$auth_type" in
+ none|owe)
+ json_get_vars owe_transition_bssid owe_transition_ssid owe_transition_ifname
+
+ [ -n "$owe_transition_ssid" ] && append bss_conf "owe_transition_ssid=\"$owe_transition_ssid\"" "$N"
+ [ -n "$owe_transition_bssid" ] && append bss_conf "owe_transition_bssid=$owe_transition_bssid" "$N"
+ [ -n "$owe_transition_ifname" ] && append bss_conf "owe_transition_ifname=$owe_transition_ifname" "$N"
+
+ wps_possible=1
+ # Here we make the assumption that if we're in open mode
+ # with WPS enabled, we got to be in unconfigured state.
+ wps_not_configured=1
+ ;;
+ psk|sae|psk-sae)
+ json_get_vars key wpa_psk_file
+ if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
+ json_get_vars auth_secret auth_port
+ set_default auth_port 1812
+ json_for_each_item append_auth_server auth_server
+ append bss_conf "macaddr_acl=2" "$N"
+ append bss_conf "wpa_psk_radius=2" "$N"
+ elif [ ${#key} -eq 64 ]; then
+ append bss_conf "wpa_psk=$key" "$N"
+ elif [ ${#key} -ge 8 ] && [ ${#key} -le 63 ]; then
+ append bss_conf "wpa_passphrase=$key" "$N"
+ elif [ -n "$key" ] || [ -z "$wpa_psk_file" ]; then
+ wireless_setup_vif_failed INVALID_WPA_PSK
+ return 1
+ fi
+ [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk
+ [ -n "$wpa_psk_file" ] && {
+ [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file"
+ append bss_conf "wpa_psk_file=$wpa_psk_file" "$N"
+ }
+ [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N"
+
+ set_default dynamic_vlan 0
+ vlan_possible=1
+ wps_possible=1
+ ;;
+ eap|eap2|eap-eap2|eap192)
+ json_get_vars \
+ auth_server auth_secret auth_port \
+ dae_client dae_secret dae_port \
+ dynamic_ownip ownip radius_client_addr \
+ eap_reauth_period request_cui \
+ erp_domain mobility_domain \
+ fils_realm fils_dhcp
+
+ # radius can provide VLAN ID for clients
+ vlan_possible=1
+
+ set_default dynamic_ownip 1
+
+ # legacy compatibility
+ [ -n "$auth_server" ] || json_get_var auth_server server
+ [ -n "$auth_port" ] || json_get_var auth_port port
+ [ -n "$auth_secret" ] || json_get_var auth_secret key
+
+ [ "$fils" -gt 0 ] && {
+ set_default erp_domain "$mobility_domain"
+ set_default erp_domain "$(echo "$ssid" | md5sum | head -c 8)"
+ set_default fils_realm "$erp_domain"
+
+ append bss_conf "erp_send_reauth_start=1" "$N"
+ append bss_conf "erp_domain=$erp_domain" "$N"
+ append bss_conf "fils_realm=$fils_realm" "$N"
+ append bss_conf "fils_cache_id=$(echo "$fils_realm" | md5sum | head -c 4)" "$N"
+
+ [ "$fils_dhcp" = "*" ] && {
+ json_get_values network network
+ fils_dhcp=
+ for net in $network; do
+ fils_dhcp="$(ifstatus "$net" | jsonfilter -e '@.data.dhcpserver')"
+ [ -n "$fils_dhcp" ] && break
+ done
+
+ [ -z "$fils_dhcp" -a -n "$network_bridge" -a -n "$network_ifname" ] && \
+ fils_dhcp="$(udhcpc -B -n -q -s /lib/netifd/dhcp-get-server.sh -t 1 -i "$network_ifname" 2>/dev/null)"
+ }
+ [ -n "$fils_dhcp" ] && append bss_conf "dhcp_server=$fils_dhcp" "$N"
+ }
+
+ set_default auth_port 1812
+ set_default dae_port 3799
+ set_default request_cui 0
+
+ [ "$eap_server" -eq 0 ] && json_for_each_item append_auth_server auth_server
+ [ "$request_cui" -gt 0 ] && append bss_conf "radius_request_cui=$request_cui" "$N"
+ [ -n "$eap_reauth_period" ] && append bss_conf "eap_reauth_period=$eap_reauth_period" "$N"
+
+ [ -n "$dae_client" -a -n "$dae_secret" ] && {
+ append bss_conf "radius_das_port=$dae_port" "$N"
+ append bss_conf "radius_das_client=$dae_client $dae_secret" "$N"
+ }
+ json_for_each_item append_radius_auth_req_attr radius_auth_req_attr
+
+ if [ -n "$ownip" ]; then
+ append bss_conf "own_ip_addr=$ownip" "$N"
+ elif [ "$dynamic_ownip" -gt 0 ]; then
+ append bss_conf "dynamic_own_ip_addr=$dynamic_ownip" "$N"
+ fi
+
+ [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
+ append bss_conf "eapol_key_index_workaround=1" "$N"
+ append bss_conf "ieee8021x=1" "$N"
+
+ [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N"
+ ;;
+ wep)
+ local wep_keyidx=0
+ json_get_vars key
+ hostapd_append_wep_key bss_conf
+ append bss_conf "wep_default_key=$wep_keyidx" "$N"
+ [ -n "$wep_rekey" ] && append bss_conf "wep_rekey_period=$wep_rekey" "$N"
+ ;;
+ esac
+
+ case "$auth_type" in
+ none|owe|psk|sae|psk-sae|wep)
+ json_get_vars \
+ auth_server auth_port auth_secret \
+ ownip radius_client_addr
+
+ [ -n "$auth_server" ] && {
+ set_default auth_port 1812
+
+ json_for_each_item append_auth_server auth_server
+ [ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N"
+ [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
+ append bss_conf "macaddr_acl=2" "$N"
+ }
+ ;;
+ esac
+
+ local auth_algs="$((($auth_mode_shared << 1) | $auth_mode_open))"
+ append bss_conf "auth_algs=${auth_algs:-1}" "$N"
+ append bss_conf "wpa=$wpa" "$N"
+ [ -n "$wpa_pairwise" ] && append bss_conf "wpa_pairwise=$wpa_pairwise" "$N"
+
+ set_default wps_pushbutton 0
+ set_default wps_label 0
+ set_default wps_pbc_in_m1 0
+
+ config_methods=
+ [ "$wps_pushbutton" -gt 0 ] && append config_methods push_button
+ [ "$wps_label" -gt 0 ] && append config_methods label
+
+ # WPS not possible on Multi-AP backhaul-only SSID
+ [ "$multi_ap" = 1 ] && wps_possible=
+
+ [ -n "$wps_possible" -a -n "$config_methods" ] && {
+ set_default ext_registrar 0
+ set_default wps_device_type "6-0050F204-1"
+ set_default wps_device_name "OpenWrt AP"
+ set_default wps_manufacturer "www.openwrt.org"
+ set_default wps_independent 1
+
+ wps_state=2
+ [ -n "$wps_not_configured" ] && wps_state=1
+
+ [ "$ext_registrar" -gt 0 -a -n "$network_bridge" ] && append bss_conf "upnp_iface=$network_bridge" "$N"
+
+ append bss_conf "eap_server=1" "$N"
+ [ -n "$wps_pin" ] && append bss_conf "ap_pin=$wps_pin" "$N"
+ append bss_conf "wps_state=$wps_state" "$N"
+ append bss_conf "device_type=$wps_device_type" "$N"
+ append bss_conf "device_name=$wps_device_name" "$N"
+ append bss_conf "manufacturer=$wps_manufacturer" "$N"
+ append bss_conf "config_methods=$config_methods" "$N"
+ append bss_conf "wps_independent=$wps_independent" "$N"
+ [ -n "$wps_ap_setup_locked" ] && append bss_conf "ap_setup_locked=$wps_ap_setup_locked" "$N"
+ [ "$wps_pbc_in_m1" -gt 0 ] && append bss_conf "pbc_in_m1=$wps_pbc_in_m1" "$N"
+ [ "$multi_ap" -gt 0 ] && [ -n "$multi_ap_backhaul_ssid" ] && {
+ append bss_conf "multi_ap_backhaul_ssid=\"$multi_ap_backhaul_ssid\"" "$N"
+ if [ -z "$multi_ap_backhaul_key" ]; then
+ :
+ elif [ ${#multi_ap_backhaul_key} -lt 8 ]; then
+ wireless_setup_vif_failed INVALID_WPA_PSK
+ return 1
+ elif [ ${#multi_ap_backhaul_key} -eq 64 ]; then
+ append bss_conf "multi_ap_backhaul_wpa_psk=$multi_ap_backhaul_key" "$N"
+ else
+ append bss_conf "multi_ap_backhaul_wpa_passphrase=$multi_ap_backhaul_key" "$N"
+ fi
+ }
+ }
+
+ append bss_conf "ssid=$ssid" "$N"
+ [ -n "$network_bridge" ] && append bss_conf "bridge=$network_bridge${N}wds_bridge=" "$N"
+ [ -n "$network_ifname" ] && append bss_conf "snoop_iface=$network_ifname" "$N"
+ [ -n "$iapp_interface" ] && {
+ local ifname
+ network_get_device ifname "$iapp_interface" || ifname="$iapp_interface"
+ append bss_conf "iapp_interface=$ifname" "$N"
+ }
+
+ json_get_vars time_advertisement time_zone wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo
+ set_default bss_transition 0
+ set_default wnm_sleep_mode 0
+ set_default wnm_sleep_mode_no_keys 0
+ set_default mbo 0
+
+ [ -n "$time_advertisement" ] && append bss_conf "time_advertisement=$time_advertisement" "$N"
+ [ -n "$time_zone" ] && append bss_conf "time_zone=$time_zone" "$N"
+ if [ "$wnm_sleep_mode" -eq "1" ]; then
+ append bss_conf "wnm_sleep_mode=1" "$N"
+ [ "$wnm_sleep_mode_no_keys" -eq "1" ] && append bss_conf "wnm_sleep_mode_no_keys=1" "$N"
+ fi
+ [ "$bss_transition" -eq "1" ] && append bss_conf "bss_transition=1" "$N"
+ [ "$mbo" -eq 1 ] && append bss_conf "mbo=1" "$N"
+
+ json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report rnr
+ set_default ieee80211k 0
+ set_default rnr 0
+ if [ "$ieee80211k" -eq "1" ]; then
+ set_default rrm_neighbor_report 1
+ set_default rrm_beacon_report 1
+ else
+ set_default rrm_neighbor_report 0
+ set_default rrm_beacon_report 0
+ fi
+
+ [ "$rrm_neighbor_report" -eq "1" ] && append bss_conf "rrm_neighbor_report=1" "$N"
+ [ "$rrm_beacon_report" -eq "1" ] && append bss_conf "rrm_beacon_report=1" "$N"
+ [ "$rnr" -eq "1" ] && append bss_conf "rnr=1" "$N"
+
+ json_get_vars ftm_responder stationary_ap lci civic
+ set_default ftm_responder 0
+ if [ "$ftm_responder" -eq "1" ]; then
+ set_default stationary_ap 0
+ iw phy "$phy" info | grep -q "ENABLE_FTM_RESPONDER" && {
+ append bss_conf "ftm_responder=1" "$N"
+ [ "$stationary_ap" -eq "1" ] && append bss_conf "stationary_ap=1" "$N"
+ [ -n "$lci" ] && append bss_conf "lci=$lci" "$N"
+ [ -n "$civic" ] && append bss_conf "civic=$civic" "$N"
+ }
+ fi
+
+ json_get_vars ieee80211r
+ set_default ieee80211r 0
+ if [ "$wpa" -ge "1" ]; then
+ if [ "$fils" -gt 0 ]; then
+ json_get_vars fils_realm
+ set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)"
+ fi
+
+ append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N"
+
+ hostapd_append_wpa_key_mgmt
+ [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N"
+ fi
+
+ if [ "$wpa" -ge "2" ]; then
+ if [ "$ieee80211r" -gt "0" ]; then
+ json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline
+
+ set_default mobility_domain "$(echo "$ssid" | md5sum | head -c 4)"
+ set_default ft_over_ds 0
+ set_default reassociation_deadline 1000
+
+ case "$auth_type" in
+ psk)
+ set_default ft_psk_generate_local 1
+ ;;
+ *)
+ set_default ft_psk_generate_local 0
+ ;;
+ esac
+
+ [ -n "$network_ifname" ] && append bss_conf "ft_iface=$network_ifname" "$N"
+ append bss_conf "mobility_domain=$mobility_domain" "$N"
+ append bss_conf "ft_psk_generate_local=$ft_psk_generate_local" "$N"
+ append bss_conf "ft_over_ds=$ft_over_ds" "$N"
+ append bss_conf "reassociation_deadline=$reassociation_deadline" "$N"
+
+ if [ "$ft_psk_generate_local" -eq "0" ]; then
+ json_get_vars r0_key_lifetime r1_key_holder pmk_r1_push
+ json_get_values r0kh r0kh
+ json_get_values r1kh r1kh
+
+ set_default r0_key_lifetime 10000
+ set_default pmk_r1_push 0
+
+ [ -n "$r0kh" -a -n "$r1kh" ] || {
+ if [ -z "$auth_secret" -a -z "$key" ]; then
+ wireless_setup_vif_failed FT_KEY_CANT_BE_DERIVED
+ return 1
+ fi
+ ft_key=`echo -n "$mobility_domain/${auth_secret:-${key}}" | md5sum | awk '{print $1}'`
+
+ set_default r0kh "ff:ff:ff:ff:ff:ff,*,$ft_key"
+ set_default r1kh "00:00:00:00:00:00,00:00:00:00:00:00,$ft_key"
+ }
+
+ [ -n "$r1_key_holder" ] && append bss_conf "r1_key_holder=$r1_key_holder" "$N"
+ append bss_conf "r0_key_lifetime=$r0_key_lifetime" "$N"
+ append bss_conf "pmk_r1_push=$pmk_r1_push" "$N"
+
+ for kh in $r0kh; do
+ append bss_conf "r0kh=${kh//,/ }" "$N"
+ done
+ for kh in $r1kh; do
+ append bss_conf "r1kh=${kh//,/ }" "$N"
+ done
+ fi
+ fi
+
+ if [ -n "$network_bridge" -a "$rsn_preauth" = 1 ]; then
+ set_default auth_cache 1
+ append bss_conf "rsn_preauth=1" "$N"
+ append bss_conf "rsn_preauth_interfaces=$network_bridge" "$N"
+ else
+ case "$auth_type" in
+ sae|psk-sae|owe)
+ set_default auth_cache 1
+ ;;
+ *)
+ set_default auth_cache 0
+ ;;
+ esac
+ fi
+
+ append bss_conf "okc=$auth_cache" "$N"
+ [ "$auth_cache" = 0 -a "$fils" = 0 ] && append bss_conf "disable_pmksa_caching=1" "$N"
+
+ # RSN -> allow management frame protection
+ case "$ieee80211w" in
+ [012])
+ json_get_vars ieee80211w_mgmt_cipher ieee80211w_max_timeout ieee80211w_retry_timeout
+ append bss_conf "ieee80211w=$ieee80211w" "$N"
+ [ "$ieee80211w" -gt "0" ] && {
+ if [ "$auth_type" = "eap192" ]; then
+ append bss_conf "group_mgmt_cipher=BIP-GMAC-256" "$N"
+ else
+ append bss_conf "group_mgmt_cipher=${ieee80211w_mgmt_cipher:-AES-128-CMAC}" "$N"
+ fi
+ [ -n "$ieee80211w_max_timeout" ] && \
+ append bss_conf "assoc_sa_query_max_timeout=$ieee80211w_max_timeout" "$N"
+ [ -n "$ieee80211w_retry_timeout" ] && \
+ append bss_conf "assoc_sa_query_retry_timeout=$ieee80211w_retry_timeout" "$N"
+ }
+ ;;
+ esac
+ fi
+
+ _macfile="/var/run/hostapd-$ifname.maclist"
+ case "$macfilter" in
+ allow)
+ append bss_conf "macaddr_acl=1" "$N"
+ append bss_conf "accept_mac_file=$_macfile" "$N"
+ # accept_mac_file can be used to set MAC to VLAN ID mapping
+ vlan_possible=1
+ ;;
+ deny)
+ append bss_conf "macaddr_acl=0" "$N"
+ append bss_conf "deny_mac_file=$_macfile" "$N"
+ ;;
+ *)
+ _macfile=""
+ ;;
+ esac
+
+ [ -n "$_macfile" ] && {
+ json_get_vars macfile
+ json_get_values maclist maclist
+
+ rm -f "$_macfile"
+ (
+ for mac in $maclist; do
+ echo "$mac"
+ done
+ [ -n "$macfile" -a -f "$macfile" ] && cat "$macfile"
+ ) > "$_macfile"
+ }
+
+ [ -n "$vlan_possible" -a -n "$dynamic_vlan" ] && {
+ json_get_vars vlan_naming vlan_tagged_interface vlan_bridge vlan_file vlan_no_bridge
+ set_default vlan_naming 1
+ [ -z "$vlan_file" ] && set_default vlan_file /var/run/hostapd-$ifname.vlan
+ append bss_conf "dynamic_vlan=$dynamic_vlan" "$N"
+ append bss_conf "vlan_naming=$vlan_naming" "$N"
+ if [ -n "$vlan_bridge" ]; then
+ append bss_conf "vlan_bridge=$vlan_bridge" "$N"
+ else
+ set_default vlan_no_bridge 1
+ fi
+ append bss_conf "vlan_no_bridge=$vlan_no_bridge" "$N"
+ [ -n "$vlan_tagged_interface" ] && \
+ append bss_conf "vlan_tagged_interface=$vlan_tagged_interface" "$N"
+ [ -n "$vlan_file" ] && {
+ [ -e "$vlan_file" ] || touch "$vlan_file"
+ append bss_conf "vlan_file=$vlan_file" "$N"
+ }
+ }
+
+ json_get_vars iw_enabled iw_internet iw_asra iw_esr iw_uesa iw_access_network_type
+ json_get_vars iw_hessid iw_venue_group iw_venue_type iw_network_auth_type
+ json_get_vars iw_roaming_consortium iw_domain_name iw_anqp_3gpp_cell_net iw_nai_realm
+ json_get_vars iw_anqp_elem iw_qos_map_set iw_ipaddr_type_availability iw_gas_address3
+ json_get_vars iw_venue_name iw_venue_url
+
+ set_default iw_enabled 0
+ if [ "$iw_enabled" = "1" ]; then
+ append bss_conf "interworking=1" "$N"
+ set_default iw_internet 1
+ set_default iw_asra 0
+ set_default iw_esr 0
+ set_default iw_uesa 0
+
+ append bss_conf "internet=$iw_internet" "$N"
+ append bss_conf "asra=$iw_asra" "$N"
+ append bss_conf "esr=$iw_esr" "$N"
+ append bss_conf "uesa=$iw_uesa" "$N"
+
+ [ -n "$iw_access_network_type" ] && \
+ append bss_conf "access_network_type=$iw_access_network_type" "$N"
+ [ -n "$iw_hessid" ] && append bss_conf "hessid=$iw_hessid" "$N"
+ [ -n "$iw_venue_group" ] && \
+ append bss_conf "venue_group=$iw_venue_group" "$N"
+ [ -n "$iw_venue_type" ] && append bss_conf "venue_type=$iw_venue_type" "$N"
+ [ -n "$iw_network_auth_type" ] && \
+ append bss_conf "network_auth_type=$iw_network_auth_type" "$N"
+ [ -n "$iw_gas_address3" ] && append bss_conf "gas_address3=$iw_gas_address3" "$N"
+
+ json_for_each_item append_iw_roaming_consortium iw_roaming_consortium
+ json_for_each_item append_iw_anqp_elem iw_anqp_elem
+ json_for_each_item append_iw_nai_realm iw_nai_realm
+ json_for_each_item append_iw_venue_name iw_venue_name
+ json_for_each_item append_iw_venue_url iw_venue_url
+
+ iw_domain_name_conf=
+ json_for_each_item append_iw_domain_name iw_domain_name
+ [ -n "$iw_domain_name_conf" ] && \
+ append bss_conf "domain_name=$iw_domain_name_conf" "$N"
+
+ iw_anqp_3gpp_cell_net_conf=
+ json_for_each_item append_iw_anqp_3gpp_cell_net iw_anqp_3gpp_cell_net
+ [ -n "$iw_anqp_3gpp_cell_net_conf" ] && \
+ append bss_conf "anqp_3gpp_cell_net=$iw_anqp_3gpp_cell_net_conf" "$N"
+ fi
+
+ set_default iw_qos_map_set 0,0,2,16,1,1,255,255,18,22,24,38,40,40,44,46,48,56
+ case "$iw_qos_map_set" in
+ *,*);;
+ *) iw_qos_map_set="";;
+ esac
+ [ -n "$iw_qos_map_set" ] && append bss_conf "qos_map_set=$iw_qos_map_set" "$N"
+
+ local hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
+ osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
+ hs20_t_c_server_url
+ json_get_vars hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
+ osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
+ hs20_t_c_server_url
+
+ set_default hs20 0
+ set_default disable_dgaf $hs20
+ set_default osen 0
+ set_default anqp_domain_id 0
+ set_default hs20_deauth_req_timeout 60
+ if [ "$hs20" = "1" ]; then
+ append bss_conf "hs20=1" "$N"
+ append_hs20_icons
+ append bss_conf "disable_dgaf=$disable_dgaf" "$N"
+ append bss_conf "osen=$osen" "$N"
+ append bss_conf "anqp_domain_id=$anqp_domain_id" "$N"
+ append bss_conf "hs20_deauth_req_timeout=$hs20_deauth_req_timeout" "$N"
+ [ -n "$osu_ssid" ] && append bss_conf "osu_ssid=$osu_ssid" "$N"
+ [ -n "$hs20_wan_metrics" ] && append bss_conf "hs20_wan_metrics=$hs20_wan_metrics" "$N"
+ [ -n "$hs20_operating_class" ] && append bss_conf "hs20_operating_class=$hs20_operating_class" "$N"
+ [ -n "$hs20_t_c_filename" ] && append bss_conf "hs20_t_c_filename=$hs20_t_c_filename" "$N"
+ [ -n "$hs20_t_c_timestamp" ] && append bss_conf "hs20_t_c_timestamp=$hs20_t_c_timestamp" "$N"
+ [ -n "$hs20_t_c_server_url" ] && append bss_conf "hs20_t_c_server_url=$hs20_t_c_server_url" "$N"
+ json_for_each_item append_hs20_oper_friendly_name hs20_oper_friendly_name
+ json_for_each_item append_hs20_conn_capab hs20_conn_capab
+ json_for_each_item append_osu_provider osu_provider
+ json_for_each_item append_operator_icon operator_icon
+ fi
+
+ if [ "$eap_server" = "1" ]; then
+ append bss_conf "eap_server=1" "$N"
+ append bss_conf "eap_server_erp=1" "$N"
+ [ -n "$eap_user_file" ] && append bss_conf "eap_user_file=$eap_user_file" "$N"
+ [ -n "$ca_cert" ] && append bss_conf "ca_cert=$ca_cert" "$N"
+ [ -n "$server_cert" ] && append bss_conf "server_cert=$server_cert" "$N"
+ [ -n "$private_key" ] && append bss_conf "private_key=$private_key" "$N"
+ [ -n "$private_key_passwd" ] && append bss_conf "private_key_passwd=$private_key_passwd" "$N"
+ [ -n "$server_id" ] && append bss_conf "server_id=$server_id" "$N"
+ fi
+
+ set_default multicast_to_unicast_all 0
+ if [ "$multicast_to_unicast_all" -gt 0 ]; then
+ append bss_conf "multicast_to_unicast=$multicast_to_unicast_all" "$N"
+ fi
+ set_default proxy_arp 0
+ if [ "$proxy_arp" -gt 0 ]; then
+ append bss_conf "proxy_arp=$proxy_arp" "$N"
+ fi
+
+ set_default per_sta_vif 0
+ if [ "$per_sta_vif" -gt 0 ]; then
+ append bss_conf "per_sta_vif=$per_sta_vif" "$N"
+ fi
+
+ json_get_values opts hostapd_bss_options
+ for val in $opts; do
+ append bss_conf "$val" "$N"
+ done
+
+ append "$var" "$bss_conf" "$N"
+ return 0
+}
+
+hostapd_set_log_options() {
+ local var="$1"
+
+ local log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
+ json_get_vars log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
+
+ set_default log_level 2
+ set_default log_80211 1
+ set_default log_8021x 1
+ set_default log_radius 1
+ set_default log_wpa 1
+ set_default log_driver 1
+ set_default log_iapp 1
+ set_default log_mlme 1
+
+ local log_mask="$(( \
+ ($log_80211 << 0) | \
+ ($log_8021x << 1) | \
+ ($log_radius << 2) | \
+ ($log_wpa << 3) | \
+ ($log_driver << 4) | \
+ ($log_iapp << 5) | \
+ ($log_mlme << 6) \
+ ))"
+
+ append "$var" "logger_syslog=$log_mask" "$N"
+ append "$var" "logger_syslog_level=$log_level" "$N"
+ append "$var" "logger_stdout=$log_mask" "$N"
+ append "$var" "logger_stdout_level=$log_level" "$N"
+
+ return 0
+}
+
+_wpa_supplicant_common() {
+ local ifname="$1"
+
+ _rpath="/var/run/wpa_supplicant"
+ _config="${_rpath}-$ifname.conf"
+}
+
+wpa_supplicant_teardown_interface() {
+ _wpa_supplicant_common "$1"
+ rm -rf "$_rpath/$1" "$_config"
+}
+
+wpa_supplicant_prepare_interface() {
+ local ifname="$1"
+ _w_driver="$2"
+
+ _wpa_supplicant_common "$1"
+
+ json_get_vars mode wds multi_ap
+
+ [ -n "$network_bridge" ] && {
+ fail=
+ case "$mode" in
+ adhoc)
+ fail=1
+ ;;
+ sta)
+ [ "$wds" = 1 -o "$multi_ap" = 1 ] || fail=1
+ ;;
+ esac
+
+ [ -n "$fail" ] && {
+ wireless_setup_vif_failed BRIDGE_NOT_ALLOWED
+ return 1
+ }
+ }
+
+ local ap_scan=
+
+ _w_mode="$mode"
+
+ [ "$mode" = adhoc ] && {
+ ap_scan="ap_scan=2"
+ }
+
+ local country_str=
+ [ -n "$country" ] && {
+ country_str="country=$country"
+ }
+
+ multiap_flag_file="${_config}.is_multiap"
+ if [ "$multi_ap" = "1" ]; then
+ touch "$multiap_flag_file"
+ else
+ [ -e "$multiap_flag_file" ] && rm "$multiap_flag_file"
+ fi
+ wpa_supplicant_teardown_interface "$ifname"
+ cat > "$_config" <<EOF
+${scan_list:+freq_list=$scan_list}
+$ap_scan
+$country_str
+EOF
+ return 0
+}
+
+wpa_supplicant_set_fixed_freq() {
+ local freq="$1"
+ local htmode="$2"
+
+ append network_data "fixed_freq=1" "$N$T"
+ append network_data "frequency=$freq" "$N$T"
+ case "$htmode" in
+ NOHT) append network_data "disable_ht=1" "$N$T";;
+ HE20|HT20|VHT20) append network_data "disable_ht40=1" "$N$T";;
+ HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160) append network_data "ht40=1" "$N$T";;
+ esac
+ case "$htmode" in
+ VHT*) append network_data "vht=1" "$N$T";;
+ esac
+ case "$htmode" in
+ HE80|VHT80) append network_data "max_oper_chwidth=1" "$N$T";;
+ HE160|VHT160) append network_data "max_oper_chwidth=2" "$N$T";;
+ HE20|HE40|VHT20|VHT40) append network_data "max_oper_chwidth=0" "$N$T";;
+ *) append network_data "disable_vht=1" "$N$T";;
+ esac
+}
+
+wpa_supplicant_add_network() {
+ local ifname="$1"
+ local freq="$2"
+ local htmode="$3"
+ local noscan="$4"
+
+ _wpa_supplicant_common "$1"
+ wireless_vif_parse_encryption
+
+ json_get_vars \
+ ssid bssid key \
+ basic_rate mcast_rate \
+ ieee80211w ieee80211r fils ocv \
+ multi_ap \
+ default_disabled
+
+ case "$auth_type" in
+ sae|owe|eap2|eap192)
+ set_default ieee80211w 2
+ ;;
+ psk-sae)
+ set_default ieee80211w 1
+ ;;
+ esac
+
+ set_default ieee80211r 0
+ set_default multi_ap 0
+ set_default default_disabled 0
+
+ local key_mgmt='NONE'
+ local network_data=
+ local T=" "
+
+ local scan_ssid="scan_ssid=1"
+ local freq wpa_key_mgmt
+
+ [ "$_w_mode" = "adhoc" ] && {
+ append network_data "mode=1" "$N$T"
+ [ -n "$freq" ] && wpa_supplicant_set_fixed_freq "$freq" "$htmode"
+ [ "$noscan" = "1" ] && append network_data "noscan=1" "$N$T"
+
+ scan_ssid="scan_ssid=0"
+
+ [ "$_w_driver" = "nl80211" ] || append wpa_key_mgmt "WPA-NONE"
+ }
+
+ [ "$_w_mode" = "mesh" ] && {
+ json_get_vars mesh_id mesh_fwding mesh_rssi_threshold encryption
+ [ -n "$mesh_id" ] && ssid="${mesh_id}"
+
+ append network_data "mode=5" "$N$T"
+ [ -n "$mesh_fwding" ] && append network_data "mesh_fwding=${mesh_fwding}" "$N$T"
+ [ -n "$mesh_rssi_threshold" ] && append network_data "mesh_rssi_threshold=${mesh_rssi_threshold}" "$N$T"
+ [ -n "$freq" ] && wpa_supplicant_set_fixed_freq "$freq" "$htmode"
+ [ "$noscan" = "1" ] && append network_data "noscan=1" "$N$T"
+ [ "$encryption" = "none" -o -z "$encryption" ] || append wpa_key_mgmt "SAE"
+ scan_ssid=""
+ }
+
+ [ "$_w_mode" = "sta" ] && {
+ [ "$multi_ap" = 1 ] && append network_data "multi_ap_backhaul_sta=1" "$N$T"
+ [ "$default_disabled" = 1 ] && append network_data "disabled=1" "$N$T"
+ }
+
+ [ -n "$ocv" ] && append network_data "ocv=$ocv" "$N$T"
+
+ case "$auth_type" in
+ none) ;;
+ owe)
+ hostapd_append_wpa_key_mgmt
+ key_mgmt="$wpa_key_mgmt"
+ ;;
+ wep)
+ local wep_keyidx=0
+ hostapd_append_wep_key network_data
+ append network_data "wep_tx_keyidx=$wep_keyidx" "$N$T"
+ ;;
+ wps)
+ key_mgmt='WPS'
+ ;;
+ psk|sae|psk-sae)
+ local passphrase
+
+ if [ "$_w_mode" != "mesh" ]; then
+ hostapd_append_wpa_key_mgmt
+ fi
+
+ key_mgmt="$wpa_key_mgmt"
+
+ if [ "$_w_mode" = "mesh" ] || [ "$auth_type" = "sae" ]; then
+ passphrase="sae_password=\"${key}\""
+ else
+ if [ ${#key} -eq 64 ]; then
+ passphrase="psk=${key}"
+ else
+ passphrase="psk=\"${key}\""
+ fi
+ fi
+ append network_data "$passphrase" "$N$T"
+ ;;
+ eap|eap2|eap192)
+ hostapd_append_wpa_key_mgmt
+ key_mgmt="$wpa_key_mgmt"
+
+ json_get_vars eap_type identity anonymous_identity ca_cert ca_cert_usesystem
+
+ [ "$fils" -gt 0 ] && append network_data "erp=1" "$N$T"
+ if [ "$ca_cert_usesystem" -eq "1" -a -f "/etc/ssl/certs/ca-certificates.crt" ]; then
+ append network_data "ca_cert=\"/etc/ssl/certs/ca-certificates.crt\"" "$N$T"
+ else
+ [ -n "$ca_cert" ] && append network_data "ca_cert=\"$ca_cert\"" "$N$T"
+ fi
+ [ -n "$identity" ] && append network_data "identity=\"$identity\"" "$N$T"
+ [ -n "$anonymous_identity" ] && append network_data "anonymous_identity=\"$anonymous_identity\"" "$N$T"
+ case "$eap_type" in
+ tls)
+ json_get_vars client_cert priv_key priv_key_pwd
+ append network_data "client_cert=\"$client_cert\"" "$N$T"
+ append network_data "private_key=\"$priv_key\"" "$N$T"
+ append network_data "private_key_passwd=\"$priv_key_pwd\"" "$N$T"
+
+ json_get_vars subject_match
+ [ -n "$subject_match" ] && append network_data "subject_match=\"$subject_match\"" "$N$T"
+
+ json_get_values altsubject_match altsubject_match
+ if [ -n "$altsubject_match" ]; then
+ local list=
+ for x in $altsubject_match; do
+ append list "$x" ";"
+ done
+ append network_data "altsubject_match=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_match domain_match
+ if [ -n "$domain_match" ]; then
+ local list=
+ for x in $domain_match; do
+ append list "$x" ";"
+ done
+ append network_data "domain_match=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_suffix_match domain_suffix_match
+ if [ -n "$domain_suffix_match" ]; then
+ local list=
+ for x in $domain_suffix_match; do
+ append list "$x" ";"
+ done
+ append network_data "domain_suffix_match=\"$list\"" "$N$T"
+ fi
+ ;;
+ fast|peap|ttls)
+ json_get_vars auth password ca_cert2 ca_cert2_usesystem client_cert2 priv_key2 priv_key2_pwd
+ set_default auth MSCHAPV2
+
+ if [ "$auth" = "EAP-TLS" ]; then
+ if [ "$ca_cert2_usesystem" -eq "1" -a -f "/etc/ssl/certs/ca-certificates.crt" ]; then
+ append network_data "ca_cert2=\"/etc/ssl/certs/ca-certificates.crt\"" "$N$T"
+ else
+ [ -n "$ca_cert2" ] && append network_data "ca_cert2=\"$ca_cert2\"" "$N$T"
+ fi
+ append network_data "client_cert2=\"$client_cert2\"" "$N$T"
+ append network_data "private_key2=\"$priv_key2\"" "$N$T"
+ append network_data "private_key2_passwd=\"$priv_key2_pwd\"" "$N$T"
+ else
+ append network_data "password=\"$password\"" "$N$T"
+ fi
+
+ json_get_vars subject_match
+ [ -n "$subject_match" ] && append network_data "subject_match=\"$subject_match\"" "$N$T"
+
+ json_get_values altsubject_match altsubject_match
+ if [ -n "$altsubject_match" ]; then
+ local list=
+ for x in $altsubject_match; do
+ append list "$x" ";"
+ done
+ append network_data "altsubject_match=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_match domain_match
+ if [ -n "$domain_match" ]; then
+ local list=
+ for x in $domain_match; do
+ append list "$x" ";"
+ done
+ append network_data "domain_match=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_suffix_match domain_suffix_match
+ if [ -n "$domain_suffix_match" ]; then
+ local list=
+ for x in $domain_suffix_match; do
+ append list "$x" ";"
+ done
+ append network_data "domain_suffix_match=\"$list\"" "$N$T"
+ fi
+
+ phase2proto="auth="
+ case "$auth" in
+ "auth"*)
+ phase2proto=""
+ ;;
+ "EAP-"*)
+ auth="$(echo $auth | cut -b 5- )"
+ [ "$eap_type" = "ttls" ] &&
+ phase2proto="autheap="
+ json_get_vars subject_match2
+ [ -n "$subject_match2" ] && append network_data "subject_match2=\"$subject_match2\"" "$N$T"
+
+ json_get_values altsubject_match2 altsubject_match2
+ if [ -n "$altsubject_match2" ]; then
+ local list=
+ for x in $altsubject_match2; do
+ append list "$x" ";"
+ done
+ append network_data "altsubject_match2=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_match2 domain_match2
+ if [ -n "$domain_match2" ]; then
+ local list=
+ for x in $domain_match2; do
+ append list "$x" ";"
+ done
+ append network_data "domain_match2=\"$list\"" "$N$T"
+ fi
+
+ json_get_values domain_suffix_match2 domain_suffix_match2
+ if [ -n "$domain_suffix_match2" ]; then
+ local list=
+ for x in $domain_suffix_match2; do
+ append list "$x" ";"
+ done
+ append network_data "domain_suffix_match2=\"$list\"" "$N$T"
+ fi
+ ;;
+ esac
+ append network_data "phase2=\"$phase2proto$auth\"" "$N$T"
+ ;;
+ esac
+ append network_data "eap=$(echo $eap_type | tr 'a-z' 'A-Z')" "$N$T"
+ ;;
+ esac
+
+ [ "$wpa_cipher" = GCMP ] && {
+ append network_data "pairwise=GCMP" "$N$T"
+ append network_data "group=GCMP" "$N$T"
+ }
+
+ [ "$mode" = mesh ] || {
+ case "$wpa" in
+ 1)
+ append network_data "proto=WPA" "$N$T"
+ ;;
+ 2)
+ append network_data "proto=RSN" "$N$T"
+ ;;
+ esac
+
+ case "$ieee80211w" in
+ [012])
+ [ "$wpa" -ge 2 ] && append network_data "ieee80211w=$ieee80211w" "$N$T"
+ ;;
+ esac
+ }
+ [ -n "$bssid" ] && append network_data "bssid=$bssid" "$N$T"
+ [ -n "$beacon_int" ] && append network_data "beacon_int=$beacon_int" "$N$T"
+
+ local bssid_blacklist bssid_whitelist
+ json_get_values bssid_blacklist bssid_blacklist
+ json_get_values bssid_whitelist bssid_whitelist
+
+ [ -n "$bssid_blacklist" ] && append network_data "bssid_blacklist=$bssid_blacklist" "$N$T"
+ [ -n "$bssid_whitelist" ] && append network_data "bssid_whitelist=$bssid_whitelist" "$N$T"
+
+ [ -n "$basic_rate" ] && {
+ local br rate_list=
+ for br in $basic_rate; do
+ wpa_supplicant_add_rate rate_list "$br"
+ done
+ [ -n "$rate_list" ] && append network_data "rates=$rate_list" "$N$T"
+ }
+
+ [ -n "$mcast_rate" ] && {
+ local mc_rate=
+ wpa_supplicant_add_rate mc_rate "$mcast_rate"
+ append network_data "mcast_rate=$mc_rate" "$N$T"
+ }
+
+ if [ "$key_mgmt" = "WPS" ]; then
+ echo "wps_cred_processing=1" >> "$_config"
+ else
+ cat >> "$_config" <<EOF
+network={
+ $scan_ssid
+ ssid="$ssid"
+ key_mgmt=$key_mgmt
+ $network_data
+}
+EOF
+ fi
+ return 0
+}
--- /dev/null
+NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
+
+. /usr/share/libubox/jshn.sh
+. $NETIFD_MAIN_DIR/utils.sh
+
+CMD_UP=0
+CMD_SET_DATA=1
+CMD_PROCESS_ADD=2
+CMD_PROCESS_KILL_ALL=3
+CMD_SET_RETRY=4
+
+add_driver() {
+ return
+}
+
+wireless_setup_vif_failed() {
+ local error="$1"
+ echo "Interface $_w_iface setup failed: $error"
+}
+
+wireless_setup_failed() {
+ local error="$1"
+
+ echo "Device setup failed: $error"
+ wireless_set_retry 0
+}
+
+prepare_key_wep() {
+ local key="$1"
+ local hex=1
+
+ echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
+ [ "${#key}" -eq 10 -a $hex -eq 1 ] || \
+ [ "${#key}" -eq 26 -a $hex -eq 1 ] || {
+ [ "${key:0:2}" = "s:" ] && key="${key#s:}"
+ key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
+ }
+ echo "$key"
+}
+
+_wdev_prepare_channel() {
+ json_get_vars channel band hwmode
+
+ auto_channel=0
+ enable_ht=0
+ htmode=
+ hwmode="${hwmode##11}"
+
+ case "$channel" in
+ ""|0|auto)
+ channel=0
+ auto_channel=1
+ ;;
+ [0-9]*) ;;
+ *)
+ wireless_setup_failed "INVALID_CHANNEL"
+ ;;
+ esac
+
+ case "$hwmode" in
+ a|b|g|ad) ;;
+ *)
+ if [ "$channel" -gt 14 ]; then
+ hwmode=a
+ else
+ hwmode=g
+ fi
+ ;;
+ esac
+
+ case "$band" in
+ 2g) hwmode=g;;
+ 5g|6g) hwmode=a;;
+ 60g) hwmode=ad;;
+ *)
+ case "$hwmode" in
+ *a) band=5g;;
+ *ad) band=60g;;
+ *b|*g) band=2g;;
+ esac
+ ;;
+ esac
+}
+
+_wdev_handler() {
+ json_load "$data"
+
+ json_select config
+ _wdev_prepare_channel
+ json_select ..
+
+ eval "drv_$1_$2 \"$interface\""
+}
+
+_wdev_msg_call() {
+ local old_cb
+
+ json_set_namespace wdev old_cb
+ "$@"
+ json_set_namespace $old_cb
+}
+
+_wdev_wrapper() {
+ while [ -n "$1" ]; do
+ eval "$1() { _wdev_msg_call _$1 \"\$@\"; }"
+ shift
+ done
+}
+
+_wdev_notify_init() {
+ local command="$1"; shift;
+
+ json_init
+ json_add_int "command" "$command"
+ json_add_string "device" "$__netifd_device"
+ while [ -n "$1" ]; do
+ local name="$1"; shift
+ local value="$1"; shift
+ json_add_string "$name" "$value"
+ done
+ json_add_object "data"
+}
+
+_wdev_notify() {
+ local options="$1"
+
+ json_close_object
+ ubus $options call network.wireless notify "$(json_dump)"
+}
+
+_wdev_add_variables() {
+ while [ -n "$1" ]; do
+ local var="${1%%=*}"
+ local val="$1"
+ shift
+ [[ "$var" = "$val" ]] && continue
+ val="${val#*=}"
+ json_add_string "$var" "$val"
+ done
+}
+
+_wireless_add_vif() {
+ local name="$1"; shift
+ local ifname="$1"; shift
+
+ _wdev_notify_init $CMD_SET_DATA "interface" "$name"
+ json_add_string "ifname" "$ifname"
+ _wdev_add_variables "$@"
+ _wdev_notify
+}
+
+_wireless_add_vlan() {
+ local name="$1"; shift
+ local ifname="$1"; shift
+
+ _wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
+ json_add_string "ifname" "$ifname"
+ _wdev_add_variables "$@"
+ _wdev_notify
+}
+
+_wireless_set_up() {
+ _wdev_notify_init $CMD_UP
+ _wdev_notify
+}
+
+_wireless_set_data() {
+ _wdev_notify_init $CMD_SET_DATA
+ _wdev_add_variables "$@"
+ _wdev_notify
+}
+
+_wireless_add_process() {
+ _wdev_notify_init $CMD_PROCESS_ADD
+ local exe="$2"
+ [ -L "$exe" ] && exe="$(readlink -f "$exe")"
+ json_add_int pid "$1"
+ json_add_string exe "$exe"
+ [ -n "$3" ] && json_add_boolean required 1
+ [ -n "$4" ] && json_add_boolean keep 1
+ exe2="$(readlink -f /proc/$1/exe)"
+ [ "$exe" != "$exe2" ] && echo "WARNING (wireless_add_process): executable path $exe does not match process $1 path ($exe2)"
+ _wdev_notify
+}
+
+_wireless_process_kill_all() {
+ _wdev_notify_init $CMD_PROCESS_KILL_ALL
+ [ -n "$1" ] && json_add_int signal "$1"
+ _wdev_notify
+}
+
+_wireless_set_retry() {
+ _wdev_notify_init $CMD_SET_RETRY
+ json_add_int retry "$1"
+ _wdev_notify
+}
+
+_wdev_wrapper \
+ wireless_add_vif \
+ wireless_add_vlan \
+ wireless_set_up \
+ wireless_set_data \
+ wireless_add_process \
+ wireless_process_kill_all \
+ wireless_set_retry \
+
+wireless_vif_parse_encryption() {
+ json_get_vars encryption
+ set_default encryption none
+
+ auth_mode_open=1
+ auth_mode_shared=0
+ auth_type=none
+
+ if [ "$hwmode" = "ad" ]; then
+ wpa_cipher="GCMP"
+ else
+ wpa_cipher="CCMP"
+ fi
+
+ case "$encryption" in
+ *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";;
+ *ccmp256) wpa_cipher="CCMP-256";;
+ *aes|*ccmp) wpa_cipher="CCMP";;
+ *tkip) wpa_cipher="TKIP";;
+ *gcmp256) wpa_cipher="GCMP-256";;
+ *gcmp) wpa_cipher="GCMP";;
+ wpa3-192*) wpa_cipher="GCMP-256";;
+ esac
+
+ # 802.11n requires CCMP for WPA
+ [ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP"
+
+ # Examples:
+ # psk-mixed/tkip => WPA1+2 PSK, TKIP
+ # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP
+ # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP
+
+ case "$encryption" in
+ wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*)
+ wpa=2
+ ;;
+ wpa*mixed*|*psk*mixed*)
+ wpa=3
+ ;;
+ wpa*|*psk*)
+ wpa=1
+ ;;
+ *)
+ wpa=0
+ wpa_cipher=
+ ;;
+ esac
+ wpa_pairwise="$wpa_cipher"
+
+ case "$encryption" in
+ owe*)
+ auth_type=owe
+ ;;
+ wpa3-192*)
+ auth_type=eap192
+ ;;
+ wpa3-mixed*)
+ auth_type=eap-eap2
+ ;;
+ wpa3*)
+ auth_type=eap2
+ ;;
+ psk3-mixed*|sae-mixed*)
+ auth_type=psk-sae
+ ;;
+ psk3*|sae*)
+ auth_type=sae
+ ;;
+ *psk*)
+ auth_type=psk
+ ;;
+ *wpa*|*8021x*)
+ auth_type=eap
+ ;;
+ *wep*)
+ auth_type=wep
+ case "$encryption" in
+ *shared*)
+ auth_mode_open=0
+ auth_mode_shared=1
+ ;;
+ *mixed*)
+ auth_mode_shared=1
+ ;;
+ esac
+ ;;
+ esac
+
+ case "$encryption" in
+ *osen*)
+ auth_osen=1
+ ;;
+ esac
+}
+
+_wireless_set_brsnoop_isolation() {
+ local multicast_to_unicast="$1"
+ local isolate
+
+ json_get_vars isolate proxy_arp
+
+ [ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return
+ [ ${multicast_to_unicast:-1} -gt 0 -o ${proxy_arp:-0} -gt 0 ] && json_add_boolean isolate 1
+}
+
+for_each_interface() {
+ local _w_types="$1"; shift
+ local _w_ifaces _w_iface
+ local _w_type
+ local _w_found
+
+ local multicast_to_unicast
+
+ json_get_keys _w_ifaces interfaces
+ json_select interfaces
+ for _w_iface in $_w_ifaces; do
+ json_select "$_w_iface"
+ if [ -n "$_w_types" ]; then
+ json_get_var network_bridge bridge
+ json_get_var network_ifname bridge-ifname
+ json_get_var multicast_to_unicast multicast_to_unicast
+ json_select config
+ _wireless_set_brsnoop_isolation "$multicast_to_unicast"
+ json_get_var _w_type mode
+ json_select ..
+ _w_types=" $_w_types "
+ [[ "${_w_types%$_w_type*}" = "$_w_types" ]] && {
+ json_select ..
+ continue
+ }
+ fi
+ __cur_interface="$_w_iface"
+ "$@" "$_w_iface"
+ json_select ..
+ done
+ json_select ..
+}
+
+for_each_vlan() {
+ local _w_vlans _w_vlan
+
+ json_get_keys _w_vlans vlans
+ json_select vlans
+ for _w_vlan in $_w_vlans; do
+ json_select "$_w_vlan"
+ json_select config
+ "$@" "$_w_vlan"
+ json_select ..
+ json_select ..
+ done
+ json_select ..
+}
+
+for_each_station() {
+ local _w_stas _w_sta
+
+ json_get_keys _w_stas stas
+ json_select stas
+ for _w_sta in $_w_stas; do
+ json_select "$_w_sta"
+ json_select config
+ "$@" "$_w_sta"
+ json_select ..
+ json_select ..
+ done
+ json_select ..
+}
+
+_wdev_common_device_config() {
+ config_add_string channel hwmode band htmode noscan
+}
+
+_wdev_common_iface_config() {
+ config_add_string mode ssid encryption 'key:wpakey'
+ config_add_boolean bridge_isolate
+}
+
+_wdev_common_vlan_config() {
+ config_add_string name vid iface
+ config_add_boolean bridge_isolate
+}
+
+_wdev_common_station_config() {
+ config_add_string mac key vid iface
+}
+
+init_wireless_driver() {
+ name="$1"; shift
+ cmd="$1"; shift
+
+ case "$cmd" in
+ dump)
+ add_driver() {
+ eval "drv_$1_cleanup"
+
+ json_init
+ json_add_string name "$1"
+
+ json_add_array device
+ _wdev_common_device_config
+ eval "drv_$1_init_device_config"
+ json_close_array
+
+ json_add_array iface
+ _wdev_common_iface_config
+ eval "drv_$1_init_iface_config"
+ json_close_array
+
+ json_add_array vlan
+ _wdev_common_vlan_config
+ eval "drv_$1_init_vlan_config"
+ json_close_array
+
+ json_add_array station
+ _wdev_common_station_config
+ eval "drv_$1_init_station_config"
+ json_close_array
+
+ json_dump
+ }
+ ;;
+ setup|teardown)
+ interface="$1"; shift
+ data="$1"; shift
+ export __netifd_device="$interface"
+
+ add_driver() {
+ [[ "$name" == "$1" ]] || return 0
+ _wdev_handler "$1" "$cmd"
+ }
+ ;;
+ esac
+}
--- /dev/null
+#!/bin/sh
+. /lib/netifd/netifd-wireless.sh
+. /lib/netifd/hostapd.sh
+. /lib/functions/system.sh
+
+init_wireless_driver "$@"
+
+MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
+ mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
+ mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
+ mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
+ mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
+ mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
+ mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
+MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
+MP_CONFIG_STRING="mesh_power_mode"
+
+wdev_tool() {
+ ucode /usr/share/hostap/wdev.uc "$@"
+}
+
+ubus_call() {
+ flock /var/run/hostapd.lock ubus call "$@"
+}
+
+drv_mac80211_init_device_config() {
+ hostapd_common_add_device_config
+
+ config_add_string path phy 'macaddr:macaddr'
+ config_add_string tx_burst
+ config_add_string distance
+ config_add_int beacon_int chanbw frag rts
+ config_add_int rxantenna txantenna txpower min_tx_power
+ config_add_int num_global_macaddr multiple_bssid
+ config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
+ config_add_array ht_capab
+ config_add_array channels
+ config_add_array scan_list
+ config_add_boolean \
+ rxldpc \
+ short_gi_80 \
+ short_gi_160 \
+ tx_stbc_2by1 \
+ su_beamformer \
+ su_beamformee \
+ mu_beamformer \
+ mu_beamformee \
+ he_su_beamformer \
+ he_su_beamformee \
+ he_mu_beamformer \
+ vht_txop_ps \
+ htc_vht \
+ rx_antenna_pattern \
+ tx_antenna_pattern \
+ he_spr_sr_control \
+ he_spr_psr_enabled \
+ he_bss_color_enabled \
+ he_twt_required
+ config_add_int \
+ beamformer_antennas \
+ beamformee_antennas \
+ vht_max_a_mpdu_len_exp \
+ vht_max_mpdu \
+ vht_link_adapt \
+ vht160 \
+ rx_stbc \
+ tx_stbc \
+ he_bss_color \
+ he_spr_non_srg_obss_pd_max_offset
+ config_add_boolean \
+ ldpc \
+ greenfield \
+ short_gi_20 \
+ short_gi_40 \
+ max_amsdu \
+ dsss_cck_40
+}
+
+drv_mac80211_init_iface_config() {
+ hostapd_common_add_bss_config
+
+ config_add_string 'macaddr:macaddr' ifname
+
+ config_add_boolean wds powersave enable
+ config_add_string wds_bridge
+ config_add_int maxassoc
+ config_add_int max_listen_int
+ config_add_int dtim_period
+ config_add_int start_disabled
+
+ # mesh
+ config_add_string mesh_id
+ config_add_int $MP_CONFIG_INT
+ config_add_boolean $MP_CONFIG_BOOL
+ config_add_string $MP_CONFIG_STRING
+}
+
+mac80211_add_capabilities() {
+ local __var="$1"; shift
+ local __mask="$1"; shift
+ local __out= oifs
+
+ oifs="$IFS"
+ IFS=:
+ for capab in "$@"; do
+ set -- $capab
+
+ [ "$(($4))" -gt 0 ] || continue
+ [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
+ __out="$__out[$1]"
+ done
+ IFS="$oifs"
+
+ export -n -- "$__var=$__out"
+}
+
+mac80211_add_he_capabilities() {
+ local __out= oifs
+
+ oifs="$IFS"
+ IFS=:
+ for capab in "$@"; do
+ set -- $capab
+ [ "$(($4))" -gt 0 ] || continue
+ [ "$(((0x$2) & $3))" -gt 0 ] || {
+ eval "$1=0"
+ continue
+ }
+ append base_cfg "$1=1" "$N"
+ done
+ IFS="$oifs"
+}
+
+mac80211_hostapd_setup_base() {
+ local phy="$1"
+
+ json_select config
+
+ [ "$auto_channel" -gt 0 ] && channel=acs_survey
+
+ [ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs
+ [ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
+ append base_cfg "acs_exclude_dfs=1" "$N"
+
+ json_get_vars noscan ht_coex min_tx_power:0 tx_burst
+ json_get_values ht_capab_list ht_capab
+ json_get_values channel_list channels
+
+ [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \
+ channel_list="$channel"
+
+ [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" "$N"
+
+ set_default noscan 0
+
+ [ "$noscan" -gt 0 ] && hostapd_noscan=1
+ [ "$tx_burst" = 0 ] && tx_burst=
+
+ chan_ofs=0
+ [ "$band" = "6g" ] && chan_ofs=1
+
+ ieee80211n=1
+ ht_capab=
+ case "$htmode" in
+ VHT20|HT20|HE20) ;;
+ HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160)
+ case "$hwmode" in
+ a)
+ case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
+ 1) ht_capab="[HT40+]";;
+ 0) ht_capab="[HT40-]";;
+ esac
+ ;;
+ *)
+ case "$htmode" in
+ HT40+) ht_capab="[HT40+]";;
+ HT40-) ht_capab="[HT40-]";;
+ *)
+ if [ "$channel" -lt 7 ]; then
+ ht_capab="[HT40+]"
+ else
+ ht_capab="[HT40-]"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ [ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
+ ;;
+ *) ieee80211n= ;;
+ esac
+
+ [ -n "$ieee80211n" ] && {
+ append base_cfg "ieee80211n=1" "$N"
+
+ set_default ht_coex 0
+ append base_cfg "ht_coex=$ht_coex" "$N"
+
+ json_get_vars \
+ ldpc:1 \
+ greenfield:0 \
+ short_gi_20:1 \
+ short_gi_40:1 \
+ tx_stbc:1 \
+ rx_stbc:3 \
+ max_amsdu:1 \
+ dsss_cck_40:1
+
+ ht_cap_mask=0
+ for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do
+ ht_cap_mask="$(($ht_cap_mask | $cap))"
+ done
+
+ cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
+ [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
+ ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
+
+ mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
+ LDPC:0x1::$ldpc \
+ GF:0x10::$greenfield \
+ SHORT-GI-20:0x20::$short_gi_20 \
+ SHORT-GI-40:0x40::$short_gi_40 \
+ TX-STBC:0x80::$tx_stbc \
+ RX-STBC1:0x300:0x100:1 \
+ RX-STBC12:0x300:0x200:1 \
+ RX-STBC123:0x300:0x300:1 \
+ MAX-AMSDU-7935:0x800::$max_amsdu \
+ DSSS_CCK-40:0x1000::$dsss_cck_40
+
+ ht_capab="$ht_capab$ht_capab_flags"
+ [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
+ }
+
+ # 802.11ac
+ enable_ac=0
+ vht_oper_chwidth=0
+ vht_center_seg0=
+
+ idx="$channel"
+ case "$htmode" in
+ VHT20|HE20) enable_ac=1;;
+ VHT40|HE40)
+ case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in
+ 1) idx=$(($channel + 2));;
+ 0) idx=$(($channel - 2));;
+ esac
+ enable_ac=1
+ vht_center_seg0=$idx
+ ;;
+ VHT80|HE80)
+ case "$(( (($channel / 4) + $chan_ofs) % 4 ))" in
+ 1) idx=$(($channel + 6));;
+ 2) idx=$(($channel + 2));;
+ 3) idx=$(($channel - 2));;
+ 0) idx=$(($channel - 6));;
+ esac
+ enable_ac=1
+ vht_oper_chwidth=1
+ vht_center_seg0=$idx
+ ;;
+ VHT160|HE160)
+ if [ "$band" = "6g" ]; then
+ case "$channel" in
+ 1|5|9|13|17|21|25|29) idx=15;;
+ 33|37|41|45|49|53|57|61) idx=47;;
+ 65|69|73|77|81|85|89|93) idx=79;;
+ 97|101|105|109|113|117|121|125) idx=111;;
+ 129|133|137|141|145|149|153|157) idx=143;;
+ 161|165|169|173|177|181|185|189) idx=175;;
+ 193|197|201|205|209|213|217|221) idx=207;;
+ esac
+ else
+ case "$channel" in
+ 36|40|44|48|52|56|60|64) idx=50;;
+ 100|104|108|112|116|120|124|128) idx=114;;
+ esac
+ fi
+ enable_ac=1
+ vht_oper_chwidth=2
+ vht_center_seg0=$idx
+ ;;
+ esac
+ [ "$band" = "5g" ] && {
+ json_get_vars background_radar:0
+
+ [ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N"
+ }
+ [ "$band" = "6g" ] && {
+ op_class=
+ case "$htmode" in
+ HE20) op_class=131;;
+ HE*) op_class=$((132 + $vht_oper_chwidth))
+ esac
+ [ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N"
+ }
+ [ "$hwmode" = "a" ] || enable_ac=0
+
+ if [ "$enable_ac" != "0" ]; then
+ json_get_vars \
+ rxldpc:1 \
+ short_gi_80:1 \
+ short_gi_160:1 \
+ tx_stbc_2by1:1 \
+ su_beamformer:1 \
+ su_beamformee:1 \
+ mu_beamformer:1 \
+ mu_beamformee:1 \
+ vht_txop_ps:1 \
+ htc_vht:1 \
+ beamformee_antennas:4 \
+ beamformer_antennas:4 \
+ rx_antenna_pattern:1 \
+ tx_antenna_pattern:1 \
+ vht_max_a_mpdu_len_exp:7 \
+ vht_max_mpdu:11454 \
+ rx_stbc:4 \
+ vht_link_adapt:3 \
+ vht160:2
+
+ set_default tx_burst 2.0
+ append base_cfg "ieee80211ac=1" "$N"
+ vht_cap=0
+ for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
+ vht_cap="$(($vht_cap | $cap))"
+ done
+
+ append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N"
+ append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
+
+ cap_rx_stbc=$((($vht_cap >> 8) & 7))
+ [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
+ vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
+
+ [ "$vht_oper_chwidth" -lt 2 ] && {
+ vht160=0
+ short_gi_160=0
+ }
+
+ mac80211_add_capabilities vht_capab $vht_cap \
+ RXLDPC:0x10::$rxldpc \
+ SHORT-GI-80:0x20::$short_gi_80 \
+ SHORT-GI-160:0x40::$short_gi_160 \
+ TX-STBC-2BY1:0x80::$tx_stbc_2by1 \
+ SU-BEAMFORMER:0x800::$su_beamformer \
+ SU-BEAMFORMEE:0x1000::$su_beamformee \
+ MU-BEAMFORMER:0x80000::$mu_beamformer \
+ MU-BEAMFORMEE:0x100000::$mu_beamformee \
+ VHT-TXOP-PS:0x200000::$vht_txop_ps \
+ HTC-VHT:0x400000::$htc_vht \
+ RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
+ TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
+ RX-STBC-1:0x700:0x100:1 \
+ RX-STBC-12:0x700:0x200:1 \
+ RX-STBC-123:0x700:0x300:1 \
+ RX-STBC-1234:0x700:0x400:1 \
+
+ [ "$(($vht_cap & 0x800))" -gt 0 -a "$su_beamformer" -gt 0 ] && {
+ cap_ant="$(( ( ($vht_cap >> 16) & 3 ) + 1 ))"
+ [ "$cap_ant" -gt "$beamformer_antennas" ] && cap_ant="$beamformer_antennas"
+ [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[SOUNDING-DIMENSION-$cap_ant]"
+ }
+
+ [ "$(($vht_cap & 0x1000))" -gt 0 -a "$su_beamformee" -gt 0 ] && {
+ cap_ant="$(( ( ($vht_cap >> 13) & 3 ) + 1 ))"
+ [ "$cap_ant" -gt "$beamformee_antennas" ] && cap_ant="$beamformee_antennas"
+ [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[BF-ANTENNA-$cap_ant]"
+ }
+
+ # supported Channel widths
+ vht160_hw=0
+ [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
+ vht160_hw=1
+ [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
+ vht160_hw=2
+ [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
+ [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
+
+ # maximum MPDU length
+ vht_max_mpdu_hw=3895
+ [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
+ vht_max_mpdu_hw=7991
+ [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
+ vht_max_mpdu_hw=11454
+ [ "$vht_max_mpdu_hw" != 3895 ] && \
+ vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
+
+ # maximum A-MPDU length exponent
+ vht_max_a_mpdu_len_exp_hw=0
+ [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=1
+ [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=2
+ [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=3
+ [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=4
+ [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=5
+ [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=6
+ [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=7
+ vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
+
+ # whether or not the STA supports link adaptation using VHT variant
+ vht_link_adapt_hw=0
+ [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
+ vht_link_adapt_hw=2
+ [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
+ vht_link_adapt_hw=3
+ [ "$vht_link_adapt_hw" != 0 ] && \
+ vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
+
+ [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
+ fi
+
+ # 802.11ax
+ enable_ax=0
+ case "$htmode" in
+ HE*) enable_ax=1 ;;
+ esac
+
+ if [ "$enable_ax" != "0" ]; then
+ json_get_vars \
+ he_su_beamformer:1 \
+ he_su_beamformee:1 \
+ he_mu_beamformer:1 \
+ he_twt_required:0 \
+ he_spr_sr_control:3 \
+ he_spr_psr_enabled:0 \
+ he_spr_non_srg_obss_pd_max_offset:0 \
+ he_bss_color:128 \
+ he_bss_color_enabled:1
+
+ he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1)
+ he_phy_cap=${he_phy_cap:2}
+ he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1)
+ he_mac_cap=${he_mac_cap:2}
+
+ append base_cfg "ieee80211ax=1" "$N"
+ [ "$hwmode" = "a" ] && {
+ append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N"
+ append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
+ }
+
+ mac80211_add_he_capabilities \
+ he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \
+ he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \
+ he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \
+ he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \
+ he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required
+
+ if [ "$he_bss_color_enabled" -gt 0 ]; then
+ append base_cfg "he_bss_color=$he_bss_color" "$N"
+ [ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \
+ append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N"
+ he_spr_sr_control=$((he_spr_sr_control | (1 << 2)))
+ }
+ [ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0)))
+ append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N"
+ else
+ append base_cfg "he_bss_color_disabled=1" "$N"
+ fi
+
+
+ append base_cfg "he_default_pe_duration=4" "$N"
+ append base_cfg "he_rts_threshold=1023" "$N"
+ append base_cfg "he_mu_edca_qos_info_param_count=0" "$N"
+ append base_cfg "he_mu_edca_qos_info_q_ack=0" "$N"
+ append base_cfg "he_mu_edca_qos_info_queue_request=0" "$N"
+ append base_cfg "he_mu_edca_qos_info_txop_request=0" "$N"
+ append base_cfg "he_mu_edca_ac_be_aifsn=8" "$N"
+ append base_cfg "he_mu_edca_ac_be_aci=0" "$N"
+ append base_cfg "he_mu_edca_ac_be_ecwmin=9" "$N"
+ append base_cfg "he_mu_edca_ac_be_ecwmax=10" "$N"
+ append base_cfg "he_mu_edca_ac_be_timer=255" "$N"
+ append base_cfg "he_mu_edca_ac_bk_aifsn=15" "$N"
+ append base_cfg "he_mu_edca_ac_bk_aci=1" "$N"
+ append base_cfg "he_mu_edca_ac_bk_ecwmin=9" "$N"
+ append base_cfg "he_mu_edca_ac_bk_ecwmax=10" "$N"
+ append base_cfg "he_mu_edca_ac_bk_timer=255" "$N"
+ append base_cfg "he_mu_edca_ac_vi_ecwmin=5" "$N"
+ append base_cfg "he_mu_edca_ac_vi_ecwmax=7" "$N"
+ append base_cfg "he_mu_edca_ac_vi_aifsn=5" "$N"
+ append base_cfg "he_mu_edca_ac_vi_aci=2" "$N"
+ append base_cfg "he_mu_edca_ac_vi_timer=255" "$N"
+ append base_cfg "he_mu_edca_ac_vo_aifsn=5" "$N"
+ append base_cfg "he_mu_edca_ac_vo_aci=3" "$N"
+ append base_cfg "he_mu_edca_ac_vo_ecwmin=5" "$N"
+ append base_cfg "he_mu_edca_ac_vo_ecwmax=7" "$N"
+ append base_cfg "he_mu_edca_ac_vo_timer=255" "$N"
+ fi
+
+ hostapd_prepare_device_config "$hostapd_conf_file" nl80211
+ cat >> "$hostapd_conf_file" <<EOF
+${channel:+channel=$channel}
+${channel_list:+chanlist=$channel_list}
+${hostapd_noscan:+noscan=1}
+${tx_burst:+tx_queue_data2_burst=$tx_burst}
+${multiple_bssid:+mbssid=$multiple_bssid}
+#num_global_macaddr=$num_global_macaddr
+$base_cfg
+
+EOF
+ json_select ..
+}
+
+mac80211_hostapd_setup_bss() {
+ local phy="$1"
+ local ifname="$2"
+ local macaddr="$3"
+ local type="$4"
+
+ hostapd_cfg=
+ append hostapd_cfg "$type=$ifname" "$N"
+
+ hostapd_set_bss_options hostapd_cfg "$phy" "$vif" || return 1
+ json_get_vars wds wds_bridge dtim_period max_listen_int start_disabled
+
+ set_default wds 0
+ set_default start_disabled 0
+
+ [ "$wds" -gt 0 ] && {
+ append hostapd_cfg "wds_sta=1" "$N"
+ [ -n "$wds_bridge" ] && append hostapd_cfg "wds_bridge=$wds_bridge" "$N"
+ }
+ [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
+
+ cat >> /var/run/hostapd-$phy.conf <<EOF
+$hostapd_cfg
+bssid=$macaddr
+${default_macaddr:+#default_macaddr}
+${dtim_period:+dtim_period=$dtim_period}
+${max_listen_int:+max_listen_interval=$max_listen_int}
+EOF
+}
+
+mac80211_get_addr() {
+ local phy="$1"
+ local idx="$(($2 + 1))"
+
+ head -n $idx /sys/class/ieee80211/${phy}/addresses | tail -n1
+}
+
+mac80211_generate_mac() {
+ local phy="$1"
+ local id="${macidx:-0}"
+
+ wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=${multiple_bssid:-0}
+}
+
+get_board_phy_name() (
+ local path="$1"
+ local fallback_phy=""
+
+ __check_phy() {
+ local val="$1"
+ local key="$2"
+ local ref_path="$3"
+
+ json_select "$key"
+ json_get_vars path
+ json_select ..
+
+ [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key
+ [ "$ref_path" = "$path" ] || return 0
+
+ echo "$key"
+ exit
+ }
+
+ json_load_file /etc/board.json
+ json_for_each_item __check_phy wlan "$path"
+ [ -n "$fallback_phy" ] && echo "${fallback_phy}.${path##*+}"
+)
+
+rename_board_phy_by_path() {
+ local path="$1"
+
+ local new_phy="$(get_board_phy_name "$path")"
+ [ -z "$new_phy" -o "$new_phy" = "$phy" ] && return
+
+ iw "$phy" set name "$new_phy" && phy="$new_phy"
+}
+
+rename_board_phy_by_name() (
+ local phy="$1"
+ local suffix="${phy##*.}"
+ [ "$suffix" = "$phy" ] && suffix=
+
+ json_load_file /etc/board.json
+ json_select wlan
+ json_select "${phy%.*}" || return 0
+ json_get_vars path
+
+ prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")"
+ [ -n "$prev_phy" ] || return 0
+
+ [ "$prev_phy" = "$phy" ] && return 0
+
+ iw "$prev_phy" set name "$phy"
+)
+
+find_phy() {
+ [ -n "$phy" ] && {
+ rename_board_phy_by_name "$phy"
+ [ -d /sys/class/ieee80211/$phy ] && return 0
+ }
+ [ -n "$path" ] && {
+ phy="$(iwinfo nl80211 phyname "path=$path")"
+ [ -n "$phy" ] && {
+ rename_board_phy_by_path "$path"
+ return 0
+ }
+ }
+ [ -n "$macaddr" ] && {
+ for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
+ grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && {
+ path="$(iwinfo nl80211 path "$phy")"
+ rename_board_phy_by_path "$path"
+ return 0
+ }
+ done
+ }
+ return 1
+}
+
+mac80211_check_ap() {
+ has_ap=1
+}
+
+mac80211_set_ifname() {
+ local phy="$1"
+ local prefix="$2"
+ eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))"
+}
+
+mac80211_prepare_vif() {
+ json_select config
+
+ json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file
+
+ [ -n "$ifname" ] || {
+ local prefix;
+
+ case "$mode" in
+ ap|sta|mesh) prefix=$mode;;
+ adhoc) prefix=ibss;;
+ monitor) prefix=mon;;
+ esac
+
+ mac80211_set_ifname "$phy" "$prefix"
+ }
+
+ append active_ifnames "$ifname"
+ set_default wds 0
+ set_default powersave 0
+ json_add_string _ifname "$ifname"
+
+ default_macaddr=
+ if [ -z "$macaddr" ]; then
+ macaddr="$(mac80211_generate_mac $phy)"
+ macidx="$(($macidx + 1))"
+ default_macaddr=1
+ elif [ "$macaddr" = 'random' ]; then
+ macaddr="$(macaddr_random)"
+ fi
+ json_add_string _macaddr "$macaddr"
+ json_add_string _default_macaddr "$default_macaddr"
+ json_select ..
+
+
+ [ "$mode" == "ap" ] && {
+ [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname"
+ [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname"
+ }
+
+ json_select config
+
+ # It is far easier to delete and create the desired interface
+ case "$mode" in
+ ap)
+ # Hostapd will handle recreating the interface and
+ # subsequent virtual APs belonging to the same PHY
+ if [ -n "$hostapd_ctrl" ]; then
+ type=bss
+ else
+ type=interface
+ fi
+
+ mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
+
+ [ -n "$hostapd_ctrl" ] || {
+ ap_ifname="${ifname}"
+ hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
+ }
+ ;;
+ esac
+
+ json_select ..
+}
+
+mac80211_prepare_iw_htmode() {
+ case "$htmode" in
+ VHT20|HT20|HE20) iw_htmode=HT20;;
+ HT40*|VHT40|VHT160|HE40)
+ case "$band" in
+ 2g)
+ case "$htmode" in
+ HT40+) iw_htmode="HT40+";;
+ HT40-) iw_htmode="HT40-";;
+ *)
+ if [ "$channel" -lt 7 ]; then
+ iw_htmode="HT40+"
+ else
+ iw_htmode="HT40-"
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ case "$(( ($channel / 4) % 2 ))" in
+ 1) iw_htmode="HT40+" ;;
+ 0) iw_htmode="HT40-";;
+ esac
+ ;;
+ esac
+ [ "$auto_channel" -gt 0 ] && iw_htmode="HT40+"
+ ;;
+ VHT80|HE80)
+ iw_htmode="80MHZ"
+ ;;
+ NONE|NOHT)
+ iw_htmode="NOHT"
+ ;;
+ *) iw_htmode="" ;;
+ esac
+}
+
+mac80211_add_mesh_params() {
+ for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
+ eval "mp_val=\"\$$var\""
+ [ -n "$mp_val" ] && json_add_string "$var" "$mp_val"
+ done
+}
+
+mac80211_setup_adhoc() {
+ local enable=$1
+ json_get_vars bssid ssid key mcast_rate
+
+ NEWUMLIST="${NEWUMLIST}$ifname "
+
+ [ "$enable" = 0 ] && {
+ ip link set dev "$ifname" down
+ return 0
+ }
+
+ keyspec=
+ [ "$auth_type" = "wep" ] && {
+ set_default key 1
+ case "$key" in
+ [1234])
+ local idx
+ for idx in 1 2 3 4; do
+ json_get_var ikey "key$idx"
+
+ [ -n "$ikey" ] && {
+ ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
+ [ $idx -eq $key ] && ikey="d:$ikey"
+ append keyspec "$ikey"
+ }
+ done
+ ;;
+ *)
+ append keyspec "d:0:$(prepare_key_wep "$key")"
+ ;;
+ esac
+ }
+
+ brstr=
+ for br in $basic_rate_list; do
+ wpa_supplicant_add_rate brstr "$br"
+ done
+
+ mcval=
+ [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
+
+ local prev
+ json_set_namespace wdev_uc prev
+
+ json_add_object "$ifname"
+ json_add_string mode adhoc
+ [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
+ json_add_string ssid "$ssid"
+ json_add_string freq "$freq"
+ json_add_string htmode "$iw_htmode"
+ [ -n "$bssid" ] && json_add_string bssid "$bssid"
+ json_add_int beacon-interval "$beacon_int"
+ [ -n "$brstr" ] && json_add_string basic-rates "$brstr"
+ [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
+ [ -n "$keyspec" ] && json_add_string keys "$keyspec"
+ json_close_object
+
+ json_set_namespace "$prev"
+}
+
+mac80211_setup_mesh() {
+ json_get_vars ssid mesh_id mcast_rate
+
+ mcval=
+ [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
+ [ -n "$mesh_id" ] && ssid="$mesh_id"
+
+ local prev
+ json_set_namespace wdev_uc prev
+
+ json_add_object "$ifname"
+ json_add_string mode mesh
+ [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
+ json_add_string ssid "$ssid"
+ json_add_string freq "$freq"
+ json_add_string htmode "$iw_htmode"
+ [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
+ json_add_int beacon-interval "$beacon_int"
+ mac80211_add_mesh_params
+
+ json_close_object
+
+ json_set_namespace "$prev"
+}
+
+mac80211_setup_monitor() {
+ local prev
+ json_set_namespace wdev_uc prev
+
+ json_add_object "$ifname"
+ json_add_string mode monitor
+ [ -n "$freq" ] && json_add_string freq "$freq"
+ json_add_string htmode "$iw_htmode"
+ json_close_object
+
+ json_set_namespace "$prev"
+}
+
+mac80211_set_vif_txpower() {
+ local name="$1"
+
+ json_select config
+ json_get_var ifname _ifname
+ json_get_vars vif_txpower
+ json_select ..
+
+ [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
+}
+
+wpa_supplicant_init_config() {
+ json_set_namespace wpa_supp prev
+
+ json_init
+ json_add_array config
+
+ json_set_namespace "$prev"
+}
+
+wpa_supplicant_add_interface() {
+ local ifname="$1"
+ local mode="$2"
+ local prev
+
+ _wpa_supplicant_common "$ifname"
+
+ json_set_namespace wpa_supp prev
+
+ json_add_object
+ json_add_string ctrl "$_rpath"
+ json_add_string iface "$ifname"
+ json_add_string mode "$mode"
+ json_add_string config "$_config"
+ [ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
+ [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
+ [ -n "$wds" ] && json_add_boolean 4addr "$wds"
+ json_add_boolean powersave "$powersave"
+ [ "$mode" = "mesh" ] && mac80211_add_mesh_params
+ json_close_object
+
+ json_set_namespace "$prev"
+
+ wpa_supp_init=1
+}
+
+wpa_supplicant_set_config() {
+ local phy="$1"
+ local prev
+
+ json_set_namespace wpa_supp prev
+ json_close_array
+ json_add_string phy "$phy"
+ json_add_boolean defer 1
+ local data="$(json_dump)"
+
+ json_cleanup
+ json_set_namespace "$prev"
+
+ ubus -S -t 0 wait_for wpa_supplicant || {
+ [ -n "$wpa_supp_init" ] || return 0
+
+ ubus wait_for wpa_supplicant
+ }
+
+ local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")"
+ ret="$?"
+ [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
+
+ wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
+
+}
+
+hostapd_set_config() {
+ [ -n "$hostapd_ctrl" ] || {
+ ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
+ return 0;
+ }
+
+ ubus wait_for hostapd
+ local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
+ ret="$?"
+ [ "$ret" != 0 -o -z "$hostapd_res" ] && {
+ wireless_setup_failed HOSTAPD_START_FAILED
+ return
+ }
+ wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1
+}
+
+
+wpa_supplicant_start() {
+ local phy="$1"
+
+ [ -n "$wpa_supp_init" ] || return 0
+
+ ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
+}
+
+mac80211_setup_supplicant() {
+ local enable=$1
+ local add_sp=0
+
+ wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
+
+ if [ "$mode" = "sta" ]; then
+ wpa_supplicant_add_network "$ifname"
+ else
+ wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$hostapd_noscan"
+ fi
+
+ wpa_supplicant_add_interface "$ifname" "$mode"
+
+ return 0
+}
+
+mac80211_setup_vif() {
+ local name="$1"
+ local failed
+
+ json_select config
+ json_get_var ifname _ifname
+ json_get_var macaddr _macaddr
+ json_get_var default_macaddr _default_macaddr
+ json_get_vars mode wds powersave
+
+ set_default powersave 0
+ set_default wds 0
+
+ case "$mode" in
+ mesh)
+ json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING
+ wireless_vif_parse_encryption
+ [ -z "$htmode" ] && htmode="NOHT";
+ if wpa_supplicant -vmesh; then
+ mac80211_setup_supplicant || failed=1
+ else
+ mac80211_setup_mesh
+ fi
+ ;;
+ adhoc)
+ wireless_vif_parse_encryption
+ if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
+ mac80211_setup_supplicant || failed=1
+ else
+ mac80211_setup_adhoc
+ fi
+ ;;
+ sta)
+ mac80211_setup_supplicant || failed=1
+ ;;
+ monitor)
+ mac80211_setup_monitor
+ ;;
+ esac
+
+ json_select ..
+ [ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
+}
+
+get_freq() {
+ local phy="$1"
+ local channel="$2"
+ local band="$3"
+
+ case "$band" in
+ 2g) band="1:";;
+ 5g) band="2:";;
+ 60g) band="3:";;
+ 6g) band="4:";;
+ esac
+
+ iw "$phy" info | awk -v band="$band" -v channel="[$channel]" '
+
+$1 ~ /Band/ {
+ band_match = band == $2
+}
+
+band_match && $3 == "MHz" && $4 == channel {
+ print $2
+ exit
+}
+'
+}
+
+chan_is_dfs() {
+ local phy="$1"
+ local chan="$2"
+ iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection"
+ return $!
+}
+
+mac80211_set_noscan() {
+ hostapd_noscan=1
+}
+
+drv_mac80211_cleanup() {
+ :
+}
+
+mac80211_reset_config() {
+ local phy="$1"
+
+ hostapd_conf_file="/var/run/hostapd-$phy.conf"
+ ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
+ ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
+ wdev_tool "$phy" set_config '{}'
+}
+
+drv_mac80211_setup() {
+ json_select config
+ json_get_vars \
+ phy macaddr path \
+ country chanbw distance \
+ txpower \
+ rxantenna txantenna \
+ frag rts beacon_int:100 htmode \
+ num_global_macaddr:1 multiple_bssid
+ json_get_values basic_rate_list basic_rate
+ json_get_values scan_list scan_list
+ json_select ..
+
+ json_select data && {
+ json_get_var prev_rxantenna rxantenna
+ json_get_var prev_txantenna txantenna
+ json_select ..
+ }
+
+ find_phy || {
+ echo "Could not find PHY for device '$1'"
+ wireless_set_retry 0
+ return 1
+ }
+
+ local wdev
+ local cwdev
+ local found
+
+ # convert channel to frequency
+ [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")"
+
+ [ -n "$country" ] && {
+ iw reg get | grep -q "^country $country:" || {
+ iw reg set "$country"
+ sleep 1
+ }
+ }
+
+ hostapd_conf_file="/var/run/hostapd-$phy.conf"
+
+ macidx=0
+ staidx=0
+
+ [ -n "$chanbw" ] && {
+ for file in /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
+ [ -f "$file" ] && echo "$chanbw" > "$file"
+ done
+ }
+
+ set_default rxantenna 0xffffffff
+ set_default txantenna 0xffffffff
+ set_default distance 0
+
+ [ "$txantenna" = "all" ] && txantenna=0xffffffff
+ [ "$rxantenna" = "all" ] && rxantenna=0xffffffff
+
+ [ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy"
+ wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna"
+
+ iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
+ iw phy "$phy" set distance "$distance" >/dev/null 2>&1
+
+ if [ -n "$txpower" ]; then
+ iw phy "$phy" set txpower fixed "${txpower%%.*}00"
+ else
+ iw phy "$phy" set txpower auto
+ fi
+
+ [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
+ [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
+
+ has_ap=
+ hostapd_ctrl=
+ ap_ifname=
+ hostapd_noscan=
+ wpa_supp_init=
+ for_each_interface "ap" mac80211_check_ap
+
+ [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev"
+
+ for_each_interface "sta adhoc mesh" mac80211_set_noscan
+ [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
+
+ local prev
+ json_set_namespace wdev_uc prev
+ json_init
+ json_set_namespace "$prev"
+
+ wpa_supplicant_init_config
+
+ mac80211_prepare_iw_htmode
+ active_ifnames=
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
+
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
+ [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
+
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
+
+ json_set_namespace wdev_uc prev
+ wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
+ json_set_namespace "$prev"
+
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
+ wireless_set_up
+}
+
+_list_phy_interfaces() {
+ local phy="$1"
+ if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
+ ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
+ else
+ ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
+ fi
+}
+
+list_phy_interfaces() {
+ local phy="$1"
+
+ for dev in $(_list_phy_interfaces "$phy"); do
+ readlink "/sys/class/net/${dev}/phy80211" | grep -q "/${phy}\$" || continue
+ echo "$dev"
+ done
+}
+
+drv_mac80211_teardown() {
+ json_select data
+ json_get_vars phy
+ json_select ..
+ [ -n "$phy" ] || {
+ echo "Bug: PHY is undefined for device '$1'"
+ return 1
+ }
+
+ mac80211_reset_config "$phy"
+
+ for wdev in $(list_phy_interfaces "$phy"); do
+ ip link set dev "$wdev" down
+ iw dev "$wdev" del
+ done
+}
+
+add_driver mac80211
--- /dev/null
+#!/bin/sh
+
+append DRIVERS "mac80211"
+
+check_mac80211_device() {
+ local device="$1"
+ local path="$2"
+ local macaddr="$3"
+
+ [ -n "$found" ] && return 0
+
+ phy_path=
+ config_get phy "$device" phy
+ json_select wlan
+ [ -n "$phy" ] && case "$phy" in
+ phy*)
+ [ -d /sys/class/ieee80211/$phy ] && \
+ phy_path="$(iwinfo nl80211 path "$dev")"
+ ;;
+ *)
+ if json_is_a "$phy" object; then
+ json_select "$phy"
+ json_get_var phy_path path
+ json_select ..
+ elif json_is_a "${phy%.*}" object; then
+ json_select "${phy%.*}"
+ json_get_var phy_path path
+ json_select ..
+ phy_path="$phy_path+${phy##*.}"
+ fi
+ ;;
+ esac
+ json_select ..
+ [ -n "$phy_path" ] || config_get phy_path "$device" path
+ [ -n "$path" -a "$phy_path" = "$path" ] && {
+ found=1
+ return 0
+ }
+
+ config_get dev_macaddr "$device" macaddr
+
+ [ -n "$macaddr" -a "$dev_macaddr" = "$macaddr" ] && found=1
+
+ return 0
+}
+
+
+__get_band_defaults() {
+ local phy="$1"
+
+ ( iw phy "$phy" info; echo ) | awk '
+BEGIN {
+ bands = ""
+}
+
+($1 == "Band" || $1 == "") && band {
+ if (channel) {
+ mode="NOHT"
+ if (ht) mode="HT20"
+ if (vht && band != "1:") mode="VHT80"
+ if (he) mode="HE80"
+ if (he && band == "1:") mode="HE20"
+ sub("\\[", "", channel)
+ sub("\\]", "", channel)
+ bands = bands band channel ":" mode " "
+ }
+ band=""
+}
+
+$1 == "Band" {
+ band = $2
+ channel = ""
+ vht = ""
+ ht = ""
+ he = ""
+}
+
+$0 ~ "Capabilities:" {
+ ht=1
+}
+
+$0 ~ "VHT Capabilities" {
+ vht=1
+}
+
+$0 ~ "HE Iftypes" {
+ he=1
+}
+
+$1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel {
+ channel = $4
+}
+
+END {
+ print bands
+}'
+}
+
+get_band_defaults() {
+ local phy="$1"
+
+ for c in $(__get_band_defaults "$phy"); do
+ local band="${c%%:*}"
+ c="${c#*:}"
+ local chan="${c%%:*}"
+ c="${c#*:}"
+ local mode="${c%%:*}"
+
+ case "$band" in
+ 1) band=2g;;
+ 2) band=5g;;
+ 3) band=60g;;
+ 4) band=6g;;
+ *) band="";;
+ esac
+
+ [ -n "$band" ] || continue
+ [ -n "$mode_band" -a "$band" = "6g" ] && return
+
+ mode_band="$band"
+ channel="$chan"
+ htmode="$mode"
+ done
+}
+
+check_devidx() {
+ case "$1" in
+ radio[0-9]*)
+ local idx="${1#radio}"
+ [ "$devidx" -ge "${1#radio}" ] && devidx=$((idx + 1))
+ ;;
+ esac
+}
+
+check_board_phy() {
+ local name="$2"
+
+ json_select "$name"
+ json_get_var phy_path path
+ json_select ..
+
+ if [ "$path" = "$phy_path" ]; then
+ board_dev="$name"
+ elif [ "${path%+*}" = "$phy_path" ]; then
+ fallback_board_dev="$name.${path#*+}"
+ fi
+}
+
+detect_mac80211() {
+ devidx=0
+ config_load wireless
+ config_foreach check_devidx wifi-device
+
+ json_load_file /etc/board.json
+
+ for _dev in /sys/class/ieee80211/*; do
+ [ -e "$_dev" ] || continue
+
+ dev="${_dev##*/}"
+
+ mode_band=""
+ channel=""
+ htmode=""
+ ht_capab=""
+
+ get_band_defaults "$dev"
+
+ path="$(iwinfo nl80211 path "$dev")"
+ macaddr="$(cat /sys/class/ieee80211/${dev}/macaddress)"
+
+ # work around phy rename related race condition
+ [ -n "$path" -o -n "$macaddr" ] || continue
+
+ board_dev=
+ fallback_board_dev=
+ json_for_each_item check_board_phy wlan
+ [ -n "$board_dev" ] || board_dev="$fallback_board_dev"
+ [ -n "$board_dev" ] && dev="$board_dev"
+
+ found=
+ config_foreach check_mac80211_device wifi-device "$path" "$macaddr"
+ [ -n "$found" ] && continue
+
+ name="radio${devidx}"
+ devidx=$(($devidx + 1))
+ case "$dev" in
+ phy*)
+ if [ -n "$path" ]; then
+ dev_id="set wireless.${name}.path='$path'"
+ else
+ dev_id="set wireless.${name}.macaddr='$macaddr'"
+ fi
+ ;;
+ *)
+ dev_id="set wireless.${name}.phy='$dev'"
+ ;;
+ esac
+
+ uci -q batch <<-EOF
+ set wireless.${name}=wifi-device
+ set wireless.${name}.type=mac80211
+ ${dev_id}
+ set wireless.${name}.channel=${channel}
+ set wireless.${name}.band=${mode_band}
+ set wireless.${name}.htmode=$htmode
+ set wireless.${name}.disabled=1
+
+ set wireless.default_${name}=wifi-iface
+ set wireless.default_${name}.device=${name}
+ set wireless.default_${name}.network=lan
+ set wireless.default_${name}.mode=ap
+ set wireless.default_${name}.ssid=OpenWrt
+ set wireless.default_${name}.encryption=none
+EOF
+ uci -q commit wireless
+ done
+}
--- /dev/null
+#!/bin/sh
+# Copyright (C) 2006 OpenWrt.org
+
+. /lib/functions.sh
+. /usr/share/libubox/jshn.sh
+
+usage() {
+ cat <<EOF
+Usage: $0 [config|up|down|reconf|reload|status|isup]
+enables (default), disables or configures devices not yet configured.
+EOF
+ exit 1
+}
+
+ubus_wifi_cmd() {
+ local cmd="$1"
+ local dev="$2"
+
+ json_init
+ [ -n "$dev" ] && json_add_string device "$dev"
+ ubus call network.wireless "$cmd" "$(json_dump)"
+}
+
+wifi_isup() {
+ local dev="$1"
+
+ json_load "$(ubus_wifi_cmd "status" "$dev")"
+ json_get_keys devices
+
+ for device in $devices; do
+ json_select "$device"
+ json_get_var up up
+ [ $up -eq 0 ] && return 1
+ json_select ..
+ done
+
+ return 0
+}
+
+find_net_config() {(
+ local vif="$1"
+ local cfg
+ local ifname
+
+ config_get cfg "$vif" network
+
+ [ -z "$cfg" ] && {
+ include /lib/network
+ scan_interfaces
+
+ config_get ifname "$vif" ifname
+
+ cfg="$(find_config "$ifname")"
+ }
+ [ -z "$cfg" ] && return 0
+ echo "$cfg"
+)}
+
+
+bridge_interface() {(
+ local cfg="$1"
+ [ -z "$cfg" ] && return 0
+
+ include /lib/network
+ scan_interfaces
+
+ for cfg in $cfg; do
+ config_get iftype "$cfg" type
+ [ "$iftype" = bridge ] && config_get "$cfg" ifname
+ prepare_interface_bridge "$cfg"
+ return $?
+ done
+)}
+
+prepare_key_wep() {
+ local key="$1"
+ local hex=1
+
+ echo -n "$key" | grep -qE "[^a-fA-F0-9]" && hex=0
+ [ "${#key}" -eq 10 -a $hex -eq 1 ] || \
+ [ "${#key}" -eq 26 -a $hex -eq 1 ] || {
+ [ "${key:0:2}" = "s:" ] && key="${key#s:}"
+ key="$(echo -n "$key" | hexdump -ve '1/1 "%02x" ""')"
+ }
+ echo "$key"
+}
+
+wifi_fixup_hwmode() {
+ local device="$1"
+ local default="$2"
+ local hwmode hwmode_11n
+
+ config_get channel "$device" channel
+ config_get hwmode "$device" hwmode
+ case "$hwmode" in
+ 11bg) hwmode=bg;;
+ 11a) hwmode=a;;
+ 11ad) hwmode=ad;;
+ 11b) hwmode=b;;
+ 11g) hwmode=g;;
+ 11n*)
+ hwmode_11n="${hwmode##11n}"
+ case "$hwmode_11n" in
+ a|g) ;;
+ default) hwmode_11n="$default"
+ esac
+ config_set "$device" hwmode_11n "$hwmode_11n"
+ ;;
+ *)
+ hwmode=
+ if [ "${channel:-0}" -gt 0 ]; then
+ if [ "${channel:-0}" -gt 14 ]; then
+ hwmode=a
+ else
+ hwmode=g
+ fi
+ else
+ hwmode="$default"
+ fi
+ ;;
+ esac
+ config_set "$device" hwmode "$hwmode"
+}
+
+_wifi_updown() {
+ for device in ${2:-$DEVICES}; do (
+ config_get disabled "$device" disabled
+ [ "$disabled" = "1" ] && {
+ echo "'$device' is disabled"
+ set disable
+ }
+ config_get iftype "$device" type
+ if eval "type ${1}_$iftype" 2>/dev/null >/dev/null; then
+ eval "scan_$iftype '$device'"
+ eval "${1}_$iftype '$device'" || echo "$device($iftype): ${1} failed"
+ elif [ ! -f /lib/netifd/wireless/$iftype.sh ]; then
+ echo "$device($iftype): Interface type not supported"
+ fi
+ ); done
+}
+
+wifi_updown() {
+ cmd=down
+ [ enable = "$1" ] && {
+ _wifi_updown disable "$2"
+ ubus_wifi_cmd "$cmd" "$2"
+ ubus call network reload
+ scan_wifi
+ cmd=up
+ }
+ [ reconf = "$1" ] && {
+ ubus call network reload
+ scan_wifi
+ cmd=reconf
+ }
+ ubus_wifi_cmd "$cmd" "$2"
+ _wifi_updown "$@"
+}
+
+wifi_reload_legacy() {
+ _wifi_updown "disable" "$1"
+ scan_wifi
+ _wifi_updown "enable" "$1"
+}
+
+wifi_reload() {
+ ubus call network reload
+ wifi_reload_legacy
+}
+
+wifi_detect_notice() {
+ >&2 echo "WARNING: Wifi detect is deprecated. Use wifi config instead"
+ >&2 echo "For more information, see commit 5f8f8a366136a07df661e31decce2458357c167a"
+ exit 1
+}
+
+wifi_config() {
+ [ -e /tmp/.config_pending ] && return
+ [ ! -f /etc/config/wireless ] && touch /etc/config/wireless
+
+ for driver in $DRIVERS; do (
+ if eval "type detect_$driver" 2>/dev/null >/dev/null; then
+ eval "detect_$driver" || echo "$driver: Detect failed" >&2
+ else
+ echo "$driver: Hardware detection not supported" >&2
+ fi
+ ); done
+}
+
+start_net() {(
+ local iface="$1"
+ local config="$2"
+ local vifmac="$3"
+
+ [ -f "/var/run/$iface.pid" ] && kill "$(cat /var/run/${iface}.pid)" 2>/dev/null
+ [ -z "$config" ] || {
+ include /lib/network
+ scan_interfaces
+ for config in $config; do
+ setup_interface "$iface" "$config" "" "$vifmac"
+ done
+ }
+)}
+
+set_wifi_up() {
+ local cfg="$1"
+ local ifname="$2"
+ uci_set_state wireless "$cfg" up 1
+ uci_set_state wireless "$cfg" ifname "$ifname"
+}
+
+set_wifi_down() {
+ local cfg="$1"
+ local vifs vif vifstr
+
+ [ -f "/var/run/wifi-${cfg}.pid" ] &&
+ kill "$(cat "/var/run/wifi-${cfg}.pid")" 2>/dev/null
+ uci_revert_state wireless "$cfg"
+ config_get vifs "$cfg" vifs
+ for vif in $vifs; do
+ uci_revert_state wireless "$vif"
+ done
+}
+
+scan_wifi() {
+ local cfgfile="$1"
+ DEVICES=
+ config_cb() {
+ local type="$1"
+ local section="$2"
+
+ # section start
+ case "$type" in
+ wifi-device)
+ append DEVICES "$section"
+ config_set "$section" vifs ""
+ config_set "$section" ht_capab ""
+ ;;
+ esac
+
+ # section end
+ config_get TYPE "$CONFIG_SECTION" TYPE
+ case "$TYPE" in
+ wifi-iface)
+ config_get device "$CONFIG_SECTION" device
+ config_get vifs "$device" vifs
+ append vifs "$CONFIG_SECTION"
+ config_set "$device" vifs "$vifs"
+ ;;
+ esac
+ }
+ config_load "${cfgfile:-wireless}"
+}
+
+DEVICES=
+DRIVERS=
+include /lib/wifi
+scan_wifi
+
+case "$1" in
+ down) wifi_updown "disable" "$2";;
+ detect) wifi_detect_notice ;;
+ config) wifi_config ;;
+ status) ubus_wifi_cmd "status" "$2";;
+ isup) wifi_isup "$2"; exit $?;;
+ reload) wifi_reload "$2";;
+ reload_legacy) wifi_reload_legacy "$2";;
+ --help|help) usage;;
+ reconf) wifi_updown "reconf" "$2";;
+ ''|up) wifi_updown "enable" "$2";;
+ *) usage; exit 1;;
+esac
--- /dev/null
+import * as nl80211 from "nl80211";
+import * as rtnl from "rtnl";
+import { readfile, glob, basename, readlink } from "fs";
+
+const iftypes = {
+ ap: nl80211.const.NL80211_IFTYPE_AP,
+ mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
+ sta: nl80211.const.NL80211_IFTYPE_STATION,
+ adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
+ monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
+};
+
+const mesh_params = {
+ mesh_retry_timeout: "retry_timeout",
+ mesh_confirm_timeout: "confirm_timeout",
+ mesh_holding_timeout: "holding_timeout",
+ mesh_max_peer_links: "max_peer_links",
+ mesh_max_retries: "max_retries",
+ mesh_ttl: "ttl",
+ mesh_element_ttl: "element_ttl",
+ mesh_auto_open_plinks: "auto_open_plinks",
+ mesh_hwmp_max_preq_retries: "hwmp_max_preq_retries",
+ mesh_path_refresh_time: "path_refresh_time",
+ mesh_min_discovery_timeout: "min_discovery_timeout",
+ mesh_hwmp_active_path_timeout: "hwmp_active_path_timeout",
+ mesh_hwmp_preq_min_interval: "hwmp_preq_min_interval",
+ mesh_hwmp_net_diameter_traversal_time: "hwmp_net_diam_trvs_time",
+ mesh_hwmp_rootmode: "hwmp_rootmode",
+ mesh_hwmp_rann_interval: "hwmp_rann_interval",
+ mesh_gate_announcements: "gate_announcements",
+ mesh_sync_offset_max_neighor: "sync_offset_max_neighbor",
+ mesh_rssi_threshold: "rssi_threshold",
+ mesh_hwmp_active_path_to_root_timeout: "hwmp_path_to_root_timeout",
+ mesh_hwmp_root_interval: "hwmp_root_interval",
+ mesh_hwmp_confirmation_interval: "hwmp_confirmation_interval",
+ mesh_awake_window: "awake_window",
+ mesh_plink_timeout: "plink_timeout",
+ mesh_fwding: "forwarding",
+ mesh_power_mode: "power_mode",
+ mesh_nolearn: "nolearn"
+};
+
+function wdev_remove(name)
+{
+ nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
+}
+
+function __phy_is_fullmac(phyidx)
+{
+ let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
+
+ return !data.software_iftypes.ap_vlan;
+}
+
+function phy_is_fullmac(phy)
+{
+ let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
+
+ return __phy_is_fullmac(phyidx);
+}
+
+function find_reusable_wdev(phyidx)
+{
+ if (!__phy_is_fullmac(phyidx))
+ return null;
+
+ let data = nl80211.request(
+ nl80211.const.NL80211_CMD_GET_INTERFACE,
+ nl80211.const.NLM_F_DUMP,
+ { wiphy: phyidx });
+ for (let res in data)
+ if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
+ return res.ifname;
+ return null;
+}
+
+function wdev_create(phy, name, data)
+{
+ let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
+
+ wdev_remove(name);
+
+ if (!iftypes[data.mode])
+ return `Invalid mode: ${data.mode}`;
+
+ let req = {
+ wiphy: phyidx,
+ ifname: name,
+ iftype: iftypes[data.mode],
+ };
+
+ if (data["4addr"])
+ req["4addr"] = data["4addr"];
+ if (data.macaddr)
+ req.mac = data.macaddr;
+
+ nl80211.error();
+
+ let reuse_ifname = find_reusable_wdev(phyidx);
+ if (reuse_ifname &&
+ (reuse_ifname == name ||
+ rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
+ nl80211.request(
+ nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
+ wiphy: phyidx,
+ dev: name,
+ iftype: iftypes[data.mode],
+ });
+ else
+ nl80211.request(
+ nl80211.const.NL80211_CMD_NEW_INTERFACE,
+ nl80211.const.NLM_F_CREATE,
+ req);
+
+ let error = nl80211.error();
+ if (error)
+ return error;
+
+ if (data.powersave != null) {
+ nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
+ { dev: name, ps_state: data.powersave ? 1 : 0});
+ }
+
+ return null;
+}
+
+function wdev_set_mesh_params(name, data)
+{
+ let mesh_cfg = {};
+
+ for (let key in mesh_params) {
+ let val = data[key];
+ if (val == null)
+ continue;
+ mesh_cfg[mesh_params[key]] = int(val);
+ }
+
+ if (!length(mesh_cfg))
+ return null;
+
+ nl80211.request(nl80211.const.NL80211_CMD_SET_MESH_CONFIG, 0,
+ { dev: name, mesh_params: mesh_cfg });
+
+ return nl80211.error();
+}
+
+function wdev_set_up(name, up)
+{
+ rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: name, change: 1, flags: up ? 1 : 0 });
+}
+
+function phy_sysfs_file(phy, name)
+{
+ return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
+}
+
+function macaddr_split(str)
+{
+ return map(split(str, ":"), (val) => hex(val));
+}
+
+function macaddr_join(addr)
+{
+ return join(":", map(addr, (val) => sprintf("%02x", val)));
+}
+
+function wdev_macaddr(wdev)
+{
+ return trim(readfile(`/sys/class/net/${wdev}/address`));
+}
+
+const phy_proto = {
+ macaddr_init: function(used, options) {
+ this.macaddr_options = options ?? {};
+ this.macaddr_list = {};
+
+ if (type(used) == "object")
+ for (let addr in used)
+ this.macaddr_list[addr] = used[addr];
+ else
+ for (let addr in used)
+ this.macaddr_list[addr] = -1;
+
+ this.for_each_wdev((wdev) => {
+ let macaddr = wdev_macaddr(wdev);
+ this.macaddr_list[macaddr] ??= -1;
+ });
+
+ return this.macaddr_list;
+ },
+
+ macaddr_generate: function(data) {
+ let phy = this.name;
+ let idx = int(data.id ?? 0);
+ let mbssid = int(data.mbssid ?? 0) > 0;
+ let num_global = int(data.num_global ?? 1);
+ let use_global = !mbssid && idx < num_global;
+
+ let base_addr = phy_sysfs_file(phy, "macaddress");
+ if (!base_addr)
+ return null;
+
+ if (!idx && !mbssid)
+ return base_addr;
+
+ let base_mask = phy_sysfs_file(phy, "address_mask");
+ if (!base_mask)
+ return null;
+
+ if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
+ let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
+
+ if (idx < length(addrs))
+ return addrs[idx];
+
+ base_mask = "ff:ff:ff:ff:ff:ff";
+ }
+
+ let addr = macaddr_split(base_addr);
+ let mask = macaddr_split(base_mask);
+ let type;
+
+ if (mbssid)
+ type = "b5";
+ else if (use_global)
+ type = "add";
+ else if (mask[0] > 0)
+ type = "b1";
+ else if (mask[5] < 0xff)
+ type = "b5";
+ else
+ type = "add";
+
+ switch (type) {
+ case "b1":
+ if (!(addr[0] & 2))
+ idx--;
+ addr[0] |= 2;
+ addr[0] ^= idx << 2;
+ break;
+ case "b5":
+ if (mbssid)
+ addr[0] |= 2;
+ addr[5] ^= idx;
+ break;
+ default:
+ for (let i = 5; i > 0; i--) {
+ addr[i] += idx;
+ if (addr[i] < 256)
+ break;
+ addr[i] %= 256;
+ }
+ break;
+ }
+
+ return macaddr_join(addr);
+ },
+
+ macaddr_next: function(val) {
+ let data = this.macaddr_options ?? {};
+ let list = this.macaddr_list;
+
+ for (let i = 0; i < 32; i++) {
+ data.id = i;
+
+ let mac = this.macaddr_generate(data);
+ if (!mac)
+ return null;
+
+ if (list[mac] != null)
+ continue;
+
+ list[mac] = val != null ? val : -1;
+ return mac;
+ }
+ },
+
+ for_each_wdev: function(cb) {
+ let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
+ wdevs = map(wdevs, (arg) => basename(arg));
+ for (let wdev in wdevs) {
+ if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
+ continue;
+
+ cb(wdev);
+ }
+ }
+};
+
+function phy_open(phy)
+{
+ let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
+ if (!phyidx)
+ return null;
+
+ return proto({
+ name: phy,
+ idx: int(phyidx)
+ }, phy_proto);
+}
+
+const vlist_proto = {
+ update: function(values, arg) {
+ let data = this.data;
+ let cb = this.cb;
+ let seq = { };
+ let new_data = {};
+ let old_data = {};
+
+ this.data = new_data;
+
+ if (type(values) == "object") {
+ for (let key in values) {
+ old_data[key] = data[key];
+ new_data[key] = values[key];
+ delete data[key];
+ }
+ } else {
+ for (let val in values) {
+ let cur_key = val[0];
+ let cur_obj = val[1];
+
+ old_data[cur_key] = data[cur_key];
+ new_data[cur_key] = val[1];
+ delete data[cur_key];
+ }
+ }
+
+ for (let key in data) {
+ cb(null, data[key], arg);
+ delete data[key];
+ }
+ for (let key in new_data)
+ cb(new_data[key], old_data[key], arg);
+ }
+};
+
+function is_equal(val1, val2) {
+ let t1 = type(val1);
+
+ if (t1 != type(val2))
+ return false;
+
+ if (t1 == "array") {
+ if (length(val1) != length(val2))
+ return false;
+
+ for (let i = 0; i < length(val1); i++)
+ if (!is_equal(val1[i], val2[i]))
+ return false;
+
+ return true;
+ } else if (t1 == "object") {
+ for (let key in val1)
+ if (!is_equal(val1[key], val2[key]))
+ return false;
+ for (let key in val2)
+ if (val1[key] == null)
+ return false;
+ return true;
+ } else {
+ return val1 == val2;
+ }
+}
+
+function vlist_new(cb) {
+ return proto({
+ cb: cb,
+ data: {}
+ }, vlist_proto);
+}
+
+export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
--- /dev/null
+#!/usr/bin/env ucode
+'use strict';
+import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
+import { readfile, writefile, basename, readlink, glob } from "fs";
+let libubus = require("ubus");
+
+let keep_devices = {};
+let phy = shift(ARGV);
+let command = shift(ARGV);
+let phydev;
+
+function iface_stop(wdev)
+{
+ if (keep_devices[wdev.ifname])
+ return;
+
+ wdev_remove(wdev.ifname);
+}
+
+function iface_start(wdev)
+{
+ let ifname = wdev.ifname;
+
+ if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
+ wdev_set_up(ifname, false);
+ wdev_remove(ifname);
+ }
+ let wdev_config = {};
+ for (let key in wdev)
+ wdev_config[key] = wdev[key];
+ if (!wdev_config.macaddr && wdev.mode != "monitor")
+ wdev_config.macaddr = phydev.macaddr_next();
+ wdev_create(phy, ifname, wdev_config);
+ wdev_set_up(ifname, true);
+ if (wdev.freq)
+ system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`);
+ if (wdev.mode == "adhoc") {
+ let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ];
+ if (wdev.bssid)
+ push(cmd, wdev.bssid);
+ for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
+ if (wdev[key])
+ push(cmd, key, wdev[key]);
+ system(cmd);
+ } else if (wdev.mode == "mesh") {
+ let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, wdev.htmode ];
+ for (let key in [ "mcast-rate", "beacon-interval" ])
+ if (wdev[key])
+ push(cmd, key, wdev[key]);
+ system(cmd);
+
+ wdev_set_mesh_params(ifname, wdev);
+ }
+}
+
+function iface_cb(new_if, old_if)
+{
+ if (old_if && new_if && is_equal(old_if, new_if))
+ return;
+
+ if (old_if)
+ iface_stop(old_if);
+ if (new_if)
+ iface_start(new_if);
+}
+
+function drop_inactive(config)
+{
+ for (let key in config) {
+ if (!readfile(`/sys/class/net/${key}/ifindex`))
+ delete config[key];
+ }
+}
+
+function add_ifname(config)
+{
+ for (let key in config)
+ config[key].ifname = key;
+}
+
+function delete_ifname(config)
+{
+ for (let key in config)
+ delete config[key].ifname;
+}
+
+function add_existing(phy, config)
+{
+ let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
+ wdevs = map(wdevs, (arg) => basename(arg));
+ for (let wdev in wdevs) {
+ if (config[wdev])
+ continue;
+
+ if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
+ continue;
+
+ if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
+ config[wdev] = {};
+ }
+}
+
+function usage()
+{
+ warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
+
+Commands:
+ set_config <config> [<device]...] - set phy configuration
+ get_macaddr <id> - get phy MAC address for vif index <id>
+`);
+ exit(1);
+}
+
+const commands = {
+ set_config: function(args) {
+ let statefile = `/var/run/wdev-${phy}.json`;
+
+ let new_config = shift(args);
+ for (let dev in ARGV)
+ keep_devices[dev] = true;
+
+ if (!new_config)
+ usage();
+
+ new_config = json(new_config);
+ if (!new_config) {
+ warn("Invalid configuration\n");
+ exit(1);
+ }
+
+ let old_config = readfile(statefile);
+ if (old_config)
+ old_config = json(old_config);
+
+ let config = vlist_new(iface_cb);
+ if (type(old_config) == "object")
+ config.data = old_config;
+
+ add_existing(phy, config.data);
+ add_ifname(config.data);
+ drop_inactive(config.data);
+
+ let ubus = libubus.connect();
+ let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
+ let macaddr_list = [];
+ if (type(data) == "object" && data.macaddr)
+ macaddr_list = data.macaddr;
+ ubus.disconnect();
+ phydev.macaddr_init(macaddr_list);
+
+ add_ifname(new_config);
+ config.update(new_config);
+
+ drop_inactive(config.data);
+ delete_ifname(config.data);
+ writefile(statefile, sprintf("%J", config.data));
+ },
+ get_macaddr: function(args) {
+ let data = {};
+
+ for (let arg in args) {
+ arg = split(arg, "=", 2);
+ data[arg[0]] = arg[1];
+ }
+
+ let macaddr = phydev.macaddr_generate(data);
+ if (!macaddr) {
+ warn(`Could not get MAC address for phy ${phy}\n`);
+ exit(1);
+ }
+
+ print(macaddr + "\n");
+ },
+};
+
+if (!phy || !command | !commands[command])
+ usage();
+
+phydev = phy_open(phy);
+if (!phydev) {
+ warn(`PHY ${phy} does not exist\n`);
+ exit(1);
+}
+
+commands[command](ARGV);
define Package/hostapd-common/install
$(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd $(1)/usr/share/acl.d $(1)/usr/share/hostap
$(INSTALL_BIN) ./files/dhcp-get-server.sh $(1)/lib/netifd/dhcp-get-server.sh
- $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh
$(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad
$(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps
$(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d
$(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities
- $(INSTALL_DATA) ./files/common.uc $(1)/usr/share/hostap/
- $(INSTALL_DATA) ./files/wdev.uc $(1)/usr/share/hostap/
endef
define Package/hostapd/install
+++ /dev/null
-import * as nl80211 from "nl80211";
-import * as rtnl from "rtnl";
-import { readfile, glob, basename, readlink } from "fs";
-
-const iftypes = {
- ap: nl80211.const.NL80211_IFTYPE_AP,
- mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
- sta: nl80211.const.NL80211_IFTYPE_STATION,
- adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
- monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
-};
-
-const mesh_params = {
- mesh_retry_timeout: "retry_timeout",
- mesh_confirm_timeout: "confirm_timeout",
- mesh_holding_timeout: "holding_timeout",
- mesh_max_peer_links: "max_peer_links",
- mesh_max_retries: "max_retries",
- mesh_ttl: "ttl",
- mesh_element_ttl: "element_ttl",
- mesh_auto_open_plinks: "auto_open_plinks",
- mesh_hwmp_max_preq_retries: "hwmp_max_preq_retries",
- mesh_path_refresh_time: "path_refresh_time",
- mesh_min_discovery_timeout: "min_discovery_timeout",
- mesh_hwmp_active_path_timeout: "hwmp_active_path_timeout",
- mesh_hwmp_preq_min_interval: "hwmp_preq_min_interval",
- mesh_hwmp_net_diameter_traversal_time: "hwmp_net_diam_trvs_time",
- mesh_hwmp_rootmode: "hwmp_rootmode",
- mesh_hwmp_rann_interval: "hwmp_rann_interval",
- mesh_gate_announcements: "gate_announcements",
- mesh_sync_offset_max_neighor: "sync_offset_max_neighbor",
- mesh_rssi_threshold: "rssi_threshold",
- mesh_hwmp_active_path_to_root_timeout: "hwmp_path_to_root_timeout",
- mesh_hwmp_root_interval: "hwmp_root_interval",
- mesh_hwmp_confirmation_interval: "hwmp_confirmation_interval",
- mesh_awake_window: "awake_window",
- mesh_plink_timeout: "plink_timeout",
- mesh_fwding: "forwarding",
- mesh_power_mode: "power_mode",
- mesh_nolearn: "nolearn"
-};
-
-function wdev_remove(name)
-{
- nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
-}
-
-function __phy_is_fullmac(phyidx)
-{
- let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
-
- return !data.software_iftypes.ap_vlan;
-}
-
-function phy_is_fullmac(phy)
-{
- let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
-
- return __phy_is_fullmac(phyidx);
-}
-
-function find_reusable_wdev(phyidx)
-{
- if (!__phy_is_fullmac(phyidx))
- return null;
-
- let data = nl80211.request(
- nl80211.const.NL80211_CMD_GET_INTERFACE,
- nl80211.const.NLM_F_DUMP,
- { wiphy: phyidx });
- for (let res in data)
- if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
- return res.ifname;
- return null;
-}
-
-function wdev_create(phy, name, data)
-{
- let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
-
- wdev_remove(name);
-
- if (!iftypes[data.mode])
- return `Invalid mode: ${data.mode}`;
-
- let req = {
- wiphy: phyidx,
- ifname: name,
- iftype: iftypes[data.mode],
- };
-
- if (data["4addr"])
- req["4addr"] = data["4addr"];
- if (data.macaddr)
- req.mac = data.macaddr;
-
- nl80211.error();
-
- let reuse_ifname = find_reusable_wdev(phyidx);
- if (reuse_ifname &&
- (reuse_ifname == name ||
- rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
- nl80211.request(
- nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
- wiphy: phyidx,
- dev: name,
- iftype: iftypes[data.mode],
- });
- else
- nl80211.request(
- nl80211.const.NL80211_CMD_NEW_INTERFACE,
- nl80211.const.NLM_F_CREATE,
- req);
-
- let error = nl80211.error();
- if (error)
- return error;
-
- if (data.powersave != null) {
- nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
- { dev: name, ps_state: data.powersave ? 1 : 0});
- }
-
- return null;
-}
-
-function wdev_set_mesh_params(name, data)
-{
- let mesh_cfg = {};
-
- for (let key in mesh_params) {
- let val = data[key];
- if (val == null)
- continue;
- mesh_cfg[mesh_params[key]] = int(val);
- }
-
- if (!length(mesh_cfg))
- return null;
-
- nl80211.request(nl80211.const.NL80211_CMD_SET_MESH_CONFIG, 0,
- { dev: name, mesh_params: mesh_cfg });
-
- return nl80211.error();
-}
-
-function wdev_set_up(name, up)
-{
- rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: name, change: 1, flags: up ? 1 : 0 });
-}
-
-function phy_sysfs_file(phy, name)
-{
- return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
-}
-
-function macaddr_split(str)
-{
- return map(split(str, ":"), (val) => hex(val));
-}
-
-function macaddr_join(addr)
-{
- return join(":", map(addr, (val) => sprintf("%02x", val)));
-}
-
-function wdev_macaddr(wdev)
-{
- return trim(readfile(`/sys/class/net/${wdev}/address`));
-}
-
-const phy_proto = {
- macaddr_init: function(used, options) {
- this.macaddr_options = options ?? {};
- this.macaddr_list = {};
-
- if (type(used) == "object")
- for (let addr in used)
- this.macaddr_list[addr] = used[addr];
- else
- for (let addr in used)
- this.macaddr_list[addr] = -1;
-
- this.for_each_wdev((wdev) => {
- let macaddr = wdev_macaddr(wdev);
- this.macaddr_list[macaddr] ??= -1;
- });
-
- return this.macaddr_list;
- },
-
- macaddr_generate: function(data) {
- let phy = this.name;
- let idx = int(data.id ?? 0);
- let mbssid = int(data.mbssid ?? 0) > 0;
- let num_global = int(data.num_global ?? 1);
- let use_global = !mbssid && idx < num_global;
-
- let base_addr = phy_sysfs_file(phy, "macaddress");
- if (!base_addr)
- return null;
-
- if (!idx && !mbssid)
- return base_addr;
-
- let base_mask = phy_sysfs_file(phy, "address_mask");
- if (!base_mask)
- return null;
-
- if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
- let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
-
- if (idx < length(addrs))
- return addrs[idx];
-
- base_mask = "ff:ff:ff:ff:ff:ff";
- }
-
- let addr = macaddr_split(base_addr);
- let mask = macaddr_split(base_mask);
- let type;
-
- if (mbssid)
- type = "b5";
- else if (use_global)
- type = "add";
- else if (mask[0] > 0)
- type = "b1";
- else if (mask[5] < 0xff)
- type = "b5";
- else
- type = "add";
-
- switch (type) {
- case "b1":
- if (!(addr[0] & 2))
- idx--;
- addr[0] |= 2;
- addr[0] ^= idx << 2;
- break;
- case "b5":
- if (mbssid)
- addr[0] |= 2;
- addr[5] ^= idx;
- break;
- default:
- for (let i = 5; i > 0; i--) {
- addr[i] += idx;
- if (addr[i] < 256)
- break;
- addr[i] %= 256;
- }
- break;
- }
-
- return macaddr_join(addr);
- },
-
- macaddr_next: function(val) {
- let data = this.macaddr_options ?? {};
- let list = this.macaddr_list;
-
- for (let i = 0; i < 32; i++) {
- data.id = i;
-
- let mac = this.macaddr_generate(data);
- if (!mac)
- return null;
-
- if (list[mac] != null)
- continue;
-
- list[mac] = val != null ? val : -1;
- return mac;
- }
- },
-
- for_each_wdev: function(cb) {
- let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
- wdevs = map(wdevs, (arg) => basename(arg));
- for (let wdev in wdevs) {
- if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
- continue;
-
- cb(wdev);
- }
- }
-};
-
-function phy_open(phy)
-{
- let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
- if (!phyidx)
- return null;
-
- return proto({
- name: phy,
- idx: int(phyidx)
- }, phy_proto);
-}
-
-const vlist_proto = {
- update: function(values, arg) {
- let data = this.data;
- let cb = this.cb;
- let seq = { };
- let new_data = {};
- let old_data = {};
-
- this.data = new_data;
-
- if (type(values) == "object") {
- for (let key in values) {
- old_data[key] = data[key];
- new_data[key] = values[key];
- delete data[key];
- }
- } else {
- for (let val in values) {
- let cur_key = val[0];
- let cur_obj = val[1];
-
- old_data[cur_key] = data[cur_key];
- new_data[cur_key] = val[1];
- delete data[cur_key];
- }
- }
-
- for (let key in data) {
- cb(null, data[key], arg);
- delete data[key];
- }
- for (let key in new_data)
- cb(new_data[key], old_data[key], arg);
- }
-};
-
-function is_equal(val1, val2) {
- let t1 = type(val1);
-
- if (t1 != type(val2))
- return false;
-
- if (t1 == "array") {
- if (length(val1) != length(val2))
- return false;
-
- for (let i = 0; i < length(val1); i++)
- if (!is_equal(val1[i], val2[i]))
- return false;
-
- return true;
- } else if (t1 == "object") {
- for (let key in val1)
- if (!is_equal(val1[key], val2[key]))
- return false;
- for (let key in val2)
- if (val1[key] == null)
- return false;
- return true;
- } else {
- return val1 == val2;
- }
-}
-
-function vlist_new(cb) {
- return proto({
- cb: cb,
- data: {}
- }, vlist_proto);
-}
-
-export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
+++ /dev/null
-. /lib/functions/network.sh
-. /lib/functions.sh
-
-wpa_supplicant_add_rate() {
- local var="$1"
- local val="$(($2 / 1000))"
- local sub="$((($2 / 100) % 10))"
- append $var "$val" ","
- [ $sub -gt 0 ] && append $var "."
-}
-
-hostapd_add_rate() {
- local var="$1"
- local val="$(($2 / 100))"
- append $var "$val" " "
-}
-
-hostapd_append_wep_key() {
- local var="$1"
-
- wep_keyidx=0
- set_default key 1
- case "$key" in
- [1234])
- for idx in 1 2 3 4; do
- local zidx
- zidx="$(($idx - 1))"
- json_get_var ckey "key${idx}"
- [ -n "$ckey" ] && \
- append $var "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N$T"
- done
- wep_keyidx="$((key - 1))"
- ;;
- *)
- append $var "wep_key0=$(prepare_key_wep "$key")" "$N$T"
- ;;
- esac
-}
-
-hostapd_append_wpa_key_mgmt() {
- local auth_type_l="$(echo $auth_type | tr 'a-z' 'A-Z')"
-
- case "$auth_type" in
- psk|eap)
- append wpa_key_mgmt "WPA-$auth_type_l"
- [ "${wpa:-2}" -ge 2 ] && [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}"
- [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-${auth_type_l}-SHA256"
- ;;
- eap192)
- append wpa_key_mgmt "WPA-EAP-SUITE-B-192"
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP-SHA384"
- ;;
- eap-eap2)
- append wpa_key_mgmt "WPA-EAP"
- append wpa_key_mgmt "WPA-EAP-SHA256"
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
- ;;
- eap2)
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-EAP"
- append wpa_key_mgmt "WPA-EAP-SHA256"
- ;;
- sae)
- append wpa_key_mgmt "SAE"
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
- ;;
- psk-sae)
- append wpa_key_mgmt "WPA-PSK"
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-PSK"
- [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-PSK-SHA256"
- append wpa_key_mgmt "SAE"
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-SAE"
- ;;
- owe)
- append wpa_key_mgmt "OWE"
- ;;
- esac
-
- [ "$fils" -gt 0 ] && {
- case "$auth_type" in
- eap-192)
- append wpa_key_mgmt FILS-SHA384
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA384
- ;;
- eap*)
- append wpa_key_mgmt FILS-SHA256
- [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt FT-FILS-SHA256
- ;;
- esac
- }
-
- [ "$auth_osen" = "1" ] && append wpa_key_mgmt "OSEN"
-}
-
-hostapd_add_log_config() {
- config_add_boolean \
- log_80211 \
- log_8021x \
- log_radius \
- log_wpa \
- log_driver \
- log_iapp \
- log_mlme
-
- config_add_int log_level
-}
-
-hostapd_common_add_device_config() {
- config_add_array basic_rate
- config_add_array supported_rates
- config_add_string beacon_rate
-
- config_add_string country country3
- config_add_boolean country_ie doth
- config_add_boolean spectrum_mgmt_required
- config_add_int local_pwr_constraint
- config_add_string require_mode
- config_add_boolean legacy_rates
- config_add_int cell_density
- config_add_int rts_threshold
- config_add_int rssi_reject_assoc_rssi
- config_add_int rssi_ignore_probe_request
- config_add_int maxassoc
-
- config_add_string acs_chan_bias
- config_add_array hostapd_options
-
- config_add_int airtime_mode
- config_add_int mbssid
-
- hostapd_add_log_config
-}
-
-hostapd_prepare_device_config() {
- local config="$1"
- local driver="$2"
-
- local base_cfg=
-
- json_get_vars country country3 country_ie beacon_int:100 doth require_mode legacy_rates \
- acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \
- rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc \
- mbssid:0
-
- hostapd_set_log_options base_cfg
-
- set_default country_ie 1
- set_default spectrum_mgmt_required 0
- set_default doth 1
- set_default legacy_rates 0
- set_default airtime_mode 0
- set_default cell_density 0
-
- [ -n "$country" ] && {
- append base_cfg "country_code=$country" "$N"
- [ -n "$country3" ] && append base_cfg "country3=$country3" "$N"
-
- [ "$country_ie" -gt 0 ] && {
- append base_cfg "ieee80211d=1" "$N"
- [ -n "$local_pwr_constraint" ] && append base_cfg "local_pwr_constraint=$local_pwr_constraint" "$N"
- [ "$spectrum_mgmt_required" -gt 0 ] && append base_cfg "spectrum_mgmt_required=$spectrum_mgmt_required" "$N"
- }
- [ "$hwmode" = "a" -a "$doth" -gt 0 ] && append base_cfg "ieee80211h=1" "$N"
- }
-
- [ -n "$acs_chan_bias" ] && append base_cfg "acs_chan_bias=$acs_chan_bias" "$N"
-
- local brlist= br
- json_get_values basic_rate_list basic_rate
- local rlist= r
- json_get_values rate_list supported_rates
-
- [ -n "$hwmode" ] && append base_cfg "hw_mode=$hwmode" "$N"
- if [ "$hwmode" = "g" ] || [ "$hwmode" = "a" ]; then
- [ -n "$require_mode" ] && legacy_rates=0
- case "$require_mode" in
- n) append base_cfg "require_ht=1" "$N";;
- ac) append base_cfg "require_vht=1" "$N";;
- esac
- fi
- case "$hwmode" in
- b)
- if [ "$cell_density" -eq 1 ]; then
- set_default rate_list "5500 11000"
- set_default basic_rate_list "5500 11000"
- elif [ "$cell_density" -ge 2 ]; then
- set_default rate_list "11000"
- set_default basic_rate_list "11000"
- fi
- ;;
- g)
- if [ "$cell_density" -eq 0 ] || [ "$cell_density" -eq 1 ]; then
- if [ "$legacy_rates" -eq 0 ]; then
- set_default rate_list "6000 9000 12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "6000 12000 24000"
- elif [ "$cell_density" -eq 1 ]; then
- set_default rate_list "5500 6000 9000 11000 12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "5500 11000"
- fi
- elif [ "$cell_density" -ge 3 ] && [ "$legacy_rates" -ne 0 ] || [ "$cell_density" -eq 2 ]; then
- if [ "$legacy_rates" -eq 0 ]; then
- set_default rate_list "12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "12000 24000"
- else
- set_default rate_list "11000 12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "11000"
- fi
- elif [ "$cell_density" -ge 3 ]; then
- set_default rate_list "24000 36000 48000 54000"
- set_default basic_rate_list "24000"
- fi
- ;;
- a)
- if [ "$cell_density" -eq 1 ]; then
- set_default rate_list "6000 9000 12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "6000 12000 24000"
- elif [ "$cell_density" -eq 2 ]; then
- set_default rate_list "12000 18000 24000 36000 48000 54000"
- set_default basic_rate_list "12000 24000"
- elif [ "$cell_density" -ge 3 ]; then
- set_default rate_list "24000 36000 48000 54000"
- set_default basic_rate_list "24000"
- fi
- ;;
- esac
-
- for r in $rate_list; do
- hostapd_add_rate rlist "$r"
- done
-
- for br in $basic_rate_list; do
- hostapd_add_rate brlist "$br"
- done
-
- [ -n "$rssi_reject_assoc_rssi" ] && append base_cfg "rssi_reject_assoc_rssi=$rssi_reject_assoc_rssi" "$N"
- [ -n "$rssi_ignore_probe_request" ] && append base_cfg "rssi_ignore_probe_request=$rssi_ignore_probe_request" "$N"
- [ -n "$beacon_rate" ] && append base_cfg "beacon_rate=$beacon_rate" "$N"
- [ -n "$rlist" ] && append base_cfg "supported_rates=$rlist" "$N"
- [ -n "$brlist" ] && append base_cfg "basic_rates=$brlist" "$N"
- append base_cfg "beacon_int=$beacon_int" "$N"
- [ -n "$rts_threshold" ] && append base_cfg "rts_threshold=$rts_threshold" "$N"
- [ "$airtime_mode" -gt 0 ] && append base_cfg "airtime_mode=$airtime_mode" "$N"
- [ -n "$maxassoc" ] && append base_cfg "iface_max_num_sta=$maxassoc" "$N"
- [ "$mbssid" -gt 0 ] && [ "$mbssid" -le 2 ] && append base_cfg "mbssid=$mbssid" "$N"
-
- json_get_values opts hostapd_options
- for val in $opts; do
- append base_cfg "$val" "$N"
- done
-
- cat > "$config" <<EOF
-driver=$driver
-$base_cfg
-EOF
-}
-
-hostapd_common_add_bss_config() {
- config_add_string 'bssid:macaddr' 'ssid:string'
- config_add_boolean wds wmm uapsd hidden utf8_ssid ppsk
-
- config_add_int maxassoc max_inactivity
- config_add_boolean disassoc_low_ack isolate short_preamble skip_inactivity_poll
-
- config_add_int \
- wep_rekey eap_reauth_period \
- wpa_group_rekey wpa_pair_rekey wpa_master_rekey
- config_add_boolean wpa_strict_rekey
- config_add_boolean wpa_disable_eapol_key_retries
-
- config_add_boolean tdls_prohibit
-
- config_add_boolean rsn_preauth auth_cache
- config_add_int ieee80211w
- config_add_int eapol_version
-
- config_add_array auth_server acct_server
- config_add_string 'server:host'
- config_add_string auth_secret key
- config_add_int 'auth_port:port' 'port:port'
-
- config_add_string acct_secret
- config_add_int acct_port
- config_add_int acct_interval
-
- config_add_int bss_load_update_period chan_util_avg_period
-
- config_add_string dae_client
- config_add_string dae_secret
- config_add_int dae_port
-
- config_add_string nasid
- config_add_string ownip
- config_add_string radius_client_addr
- config_add_string iapp_interface
- config_add_string eap_type ca_cert client_cert identity anonymous_identity auth priv_key priv_key_pwd
- config_add_boolean ca_cert_usesystem ca_cert2_usesystem
- config_add_string subject_match subject_match2
- config_add_array altsubject_match altsubject_match2
- config_add_array domain_match domain_match2 domain_suffix_match domain_suffix_match2
- config_add_string ieee80211w_mgmt_cipher
-
- config_add_int dynamic_vlan vlan_naming vlan_no_bridge
- config_add_string vlan_tagged_interface vlan_bridge
- config_add_string vlan_file
-
- config_add_string 'key1:wepkey' 'key2:wepkey' 'key3:wepkey' 'key4:wepkey' 'password:wpakey'
-
- config_add_string wpa_psk_file
-
- config_add_int multi_ap
-
- config_add_boolean wps_pushbutton wps_label ext_registrar wps_pbc_in_m1
- config_add_int wps_ap_setup_locked wps_independent
- config_add_string wps_device_type wps_device_name wps_manufacturer wps_pin
- config_add_string multi_ap_backhaul_ssid multi_ap_backhaul_key
-
- config_add_boolean wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo
- config_add_int time_advertisement
- config_add_string time_zone
- config_add_string vendor_elements
-
- config_add_boolean ieee80211k rrm_neighbor_report rrm_beacon_report
-
- config_add_boolean ftm_responder stationary_ap
- config_add_string lci civic
-
- config_add_boolean ieee80211r pmk_r1_push ft_psk_generate_local ft_over_ds
- config_add_int r0_key_lifetime reassociation_deadline
- config_add_string mobility_domain r1_key_holder
- config_add_array r0kh r1kh
-
- config_add_int ieee80211w_max_timeout ieee80211w_retry_timeout
-
- config_add_string macfilter 'macfile:file'
- config_add_array 'maclist:list(macaddr)'
-
- config_add_array bssid_blacklist
- config_add_array bssid_whitelist
-
- config_add_int mcast_rate
- config_add_array basic_rate
- config_add_array supported_rates
-
- config_add_boolean sae_require_mfp
- config_add_int sae_pwe
-
- config_add_string 'owe_transition_bssid:macaddr' 'owe_transition_ssid:string'
- config_add_string owe_transition_ifname
-
- config_add_boolean iw_enabled iw_internet iw_asra iw_esr iw_uesa
- config_add_int iw_access_network_type iw_venue_group iw_venue_type
- config_add_int iw_ipaddr_type_availability iw_gas_address3
- config_add_string iw_hessid iw_network_auth_type iw_qos_map_set
- config_add_array iw_roaming_consortium iw_domain_name iw_anqp_3gpp_cell_net iw_nai_realm
- config_add_array iw_anqp_elem iw_venue_name iw_venue_url
-
- config_add_boolean hs20 disable_dgaf osen
- config_add_int anqp_domain_id
- config_add_int hs20_deauth_req_timeout
- config_add_array hs20_oper_friendly_name
- config_add_array osu_provider
- config_add_array operator_icon
- config_add_array hs20_conn_capab
- config_add_string osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp
-
- config_add_string hs20_t_c_server_url
-
- config_add_array airtime_sta_weight
- config_add_int airtime_bss_weight airtime_bss_limit
-
- config_add_boolean multicast_to_unicast multicast_to_unicast_all proxy_arp per_sta_vif
-
- config_add_array hostapd_bss_options
- config_add_boolean default_disabled
-
- config_add_boolean request_cui
- config_add_array radius_auth_req_attr
- config_add_array radius_acct_req_attr
-
- config_add_int eap_server
- config_add_string eap_user_file ca_cert server_cert private_key private_key_passwd server_id
-
- config_add_boolean fils
- config_add_string fils_dhcp
-
- config_add_int ocv
-}
-
-hostapd_set_vlan_file() {
- local ifname="$1"
- local vlan="$2"
- json_get_vars name vid
- echo "${vid} ${ifname}-${name}" >> /var/run/hostapd-${ifname}.vlan
- wireless_add_vlan "${vlan}" "${ifname}-${name}"
-}
-
-hostapd_set_vlan() {
- local ifname="$1"
-
- rm -f /var/run/hostapd-${ifname}.vlan
- for_each_vlan hostapd_set_vlan_file ${ifname}
-}
-
-hostapd_set_psk_file() {
- local ifname="$1"
- local vlan="$2"
- local vlan_id=""
-
- json_get_vars mac vid key
- set_default mac "00:00:00:00:00:00"
- [ -n "$vid" ] && vlan_id="vlanid=$vid "
- echo "${vlan_id} ${mac} ${key}" >> /var/run/hostapd-${ifname}.psk
-}
-
-hostapd_set_psk() {
- local ifname="$1"
-
- rm -f /var/run/hostapd-${ifname}.psk
- for_each_station hostapd_set_psk_file ${ifname}
-}
-
-append_iw_roaming_consortium() {
- [ -n "$1" ] && append bss_conf "roaming_consortium=$1" "$N"
-}
-
-append_iw_domain_name() {
- if [ -z "$iw_domain_name_conf" ]; then
- iw_domain_name_conf="$1"
- else
- iw_domain_name_conf="$iw_domain_name_conf,$1"
- fi
-}
-
-append_iw_anqp_3gpp_cell_net() {
- if [ -z "$iw_anqp_3gpp_cell_net_conf" ]; then
- iw_anqp_3gpp_cell_net_conf="$1"
- else
- iw_anqp_3gpp_cell_net_conf="$iw_anqp_3gpp_cell_net_conf:$1"
- fi
-}
-
-append_iw_anqp_elem() {
- [ -n "$1" ] && append bss_conf "anqp_elem=$1" "$N"
-}
-
-append_iw_nai_realm() {
- [ -n "$1" ] && append bss_conf "nai_realm=$1" "$N"
-}
-
-append_iw_venue_name() {
- append bss_conf "venue_name=$1" "$N"
-}
-
-append_iw_venue_url() {
- append bss_conf "venue_url=$1" "$N"
-}
-
-append_hs20_oper_friendly_name() {
- append bss_conf "hs20_oper_friendly_name=$1" "$N"
-}
-
-append_osu_provider_friendly_name() {
- append bss_conf "osu_friendly_name=$1" "$N"
-}
-
-append_osu_provider_service_desc() {
- append bss_conf "osu_service_desc=$1" "$N"
-}
-
-append_hs20_icon() {
- local width height lang type path
- config_get width "$1" width
- config_get height "$1" height
- config_get lang "$1" lang
- config_get type "$1" type
- config_get path "$1" path
-
- append bss_conf "hs20_icon=$width:$height:$lang:$type:$1:$path" "$N"
-}
-
-append_hs20_icons() {
- config_load wireless
- config_foreach append_hs20_icon hs20-icon
-}
-
-append_operator_icon() {
- append bss_conf "operator_icon=$1" "$N"
-}
-
-append_osu_icon() {
- append bss_conf "osu_icon=$1" "$N"
-}
-
-append_osu_provider() {
- local cfgtype osu_server_uri osu_friendly_name osu_nai osu_nai2 osu_method_list
-
- config_load wireless
- config_get cfgtype "$1" TYPE
- [ "$cfgtype" != "osu-provider" ] && return
-
- append bss_conf "# provider $1" "$N"
- config_get osu_server_uri "$1" osu_server_uri
- config_get osu_nai "$1" osu_nai
- config_get osu_nai2 "$1" osu_nai2
- config_get osu_method_list "$1" osu_method
-
- append bss_conf "osu_server_uri=$osu_server_uri" "$N"
- append bss_conf "osu_nai=$osu_nai" "$N"
- append bss_conf "osu_nai2=$osu_nai2" "$N"
- append bss_conf "osu_method_list=$osu_method_list" "$N"
-
- config_list_foreach "$1" osu_service_desc append_osu_provider_service_desc
- config_list_foreach "$1" osu_friendly_name append_osu_friendly_name
- config_list_foreach "$1" osu_icon append_osu_icon
-
- append bss_conf "$N"
-}
-
-append_hs20_conn_capab() {
- [ -n "$1" ] && append bss_conf "hs20_conn_capab=$1" "$N"
-}
-
-append_radius_acct_req_attr() {
- [ -n "$1" ] && append bss_conf "radius_acct_req_attr=$1" "$N"
-}
-
-append_radius_auth_req_attr() {
- [ -n "$1" ] && append bss_conf "radius_auth_req_attr=$1" "$N"
-}
-
-append_airtime_sta_weight() {
- [ -n "$1" ] && append bss_conf "airtime_sta_weight=$1" "$N"
-}
-
-append_auth_server() {
- [ -n "$1" ] || return
- append bss_conf "auth_server_addr=$1" "$N"
- append bss_conf "auth_server_port=$auth_port" "$N"
- [ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
-}
-
-append_acct_server() {
- [ -n "$1" ] || return
- append bss_conf "acct_server_addr=$1" "$N"
- append bss_conf "acct_server_port=$acct_port" "$N"
- [ -n "$acct_secret" ] && append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
-}
-
-hostapd_set_bss_options() {
- local var="$1"
- local phy="$2"
- local vif="$3"
-
- wireless_vif_parse_encryption
-
- local bss_conf bss_md5sum ft_key
- local wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wpa_key_mgmt
-
- json_get_vars \
- wep_rekey wpa_group_rekey wpa_pair_rekey wpa_master_rekey wpa_strict_rekey \
- wpa_disable_eapol_key_retries tdls_prohibit \
- maxassoc max_inactivity disassoc_low_ack isolate auth_cache \
- wps_pushbutton wps_label ext_registrar wps_pbc_in_m1 wps_ap_setup_locked \
- wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \
- macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
- iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
- acct_secret acct_port acct_interval \
- bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \
- multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \
- ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \
- multicast_to_unicast_all proxy_arp per_sta_vif \
- eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id \
- vendor_elements fils ocv
-
- set_default fils 0
- set_default isolate 0
- set_default maxassoc 0
- set_default max_inactivity 0
- set_default short_preamble 1
- set_default disassoc_low_ack 1
- set_default skip_inactivity_poll 0
- set_default hidden 0
- set_default wmm 1
- set_default uapsd 1
- set_default wpa_disable_eapol_key_retries 0
- set_default tdls_prohibit 0
- set_default eapol_version $((wpa & 1))
- set_default acct_port 1813
- set_default bss_load_update_period 60
- set_default chan_util_avg_period 600
- set_default utf8_ssid 1
- set_default multi_ap 0
- set_default ppsk 0
- set_default airtime_bss_weight 0
- set_default airtime_bss_limit 0
- set_default eap_server 0
-
- /usr/sbin/hostapd -vfils || fils=0
-
- append bss_conf "ctrl_interface=/var/run/hostapd"
- if [ "$isolate" -gt 0 ]; then
- append bss_conf "ap_isolate=$isolate" "$N"
- fi
- if [ "$maxassoc" -gt 0 ]; then
- append bss_conf "max_num_sta=$maxassoc" "$N"
- fi
- if [ "$max_inactivity" -gt 0 ]; then
- append bss_conf "ap_max_inactivity=$max_inactivity" "$N"
- fi
-
- [ "$airtime_bss_weight" -gt 0 ] && append bss_conf "airtime_bss_weight=$airtime_bss_weight" "$N"
- [ "$airtime_bss_limit" -gt 0 ] && append bss_conf "airtime_bss_limit=$airtime_bss_limit" "$N"
- json_for_each_item append_airtime_sta_weight airtime_sta_weight
-
- append bss_conf "bss_load_update_period=$bss_load_update_period" "$N"
- append bss_conf "chan_util_avg_period=$chan_util_avg_period" "$N"
- append bss_conf "disassoc_low_ack=$disassoc_low_ack" "$N"
- append bss_conf "skip_inactivity_poll=$skip_inactivity_poll" "$N"
- append bss_conf "preamble=$short_preamble" "$N"
- append bss_conf "wmm_enabled=$wmm" "$N"
- append bss_conf "ignore_broadcast_ssid=$hidden" "$N"
- append bss_conf "uapsd_advertisement_enabled=$uapsd" "$N"
- append bss_conf "utf8_ssid=$utf8_ssid" "$N"
- append bss_conf "multi_ap=$multi_ap" "$N"
- [ -n "$vendor_elements" ] && append bss_conf "vendor_elements=$vendor_elements" "$N"
-
- [ "$tdls_prohibit" -gt 0 ] && append bss_conf "tdls_prohibit=$tdls_prohibit" "$N"
-
- [ "$wpa" -gt 0 ] && {
- [ -n "$wpa_group_rekey" ] && append bss_conf "wpa_group_rekey=$wpa_group_rekey" "$N"
- [ -n "$wpa_pair_rekey" ] && append bss_conf "wpa_ptk_rekey=$wpa_pair_rekey" "$N"
- [ -n "$wpa_master_rekey" ] && append bss_conf "wpa_gmk_rekey=$wpa_master_rekey" "$N"
- [ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
- }
-
- [ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
-
- [ -n "$acct_interval" ] && \
- append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
- json_for_each_item append_acct_server acct_server
- json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
-
- [ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N"
-
- case "$auth_type" in
- sae|owe|eap2|eap192)
- set_default ieee80211w 2
- set_default sae_require_mfp 1
- set_default sae_pwe 2
- ;;
- psk-sae|eap-eap2)
- set_default ieee80211w 1
- set_default sae_require_mfp 1
- set_default sae_pwe 2
- ;;
- esac
- [ -n "$sae_require_mfp" ] && append bss_conf "sae_require_mfp=$sae_require_mfp" "$N"
- [ -n "$sae_pwe" ] && append bss_conf "sae_pwe=$sae_pwe" "$N"
-
- local vlan_possible=""
-
- case "$auth_type" in
- none|owe)
- json_get_vars owe_transition_bssid owe_transition_ssid owe_transition_ifname
-
- [ -n "$owe_transition_ssid" ] && append bss_conf "owe_transition_ssid=\"$owe_transition_ssid\"" "$N"
- [ -n "$owe_transition_bssid" ] && append bss_conf "owe_transition_bssid=$owe_transition_bssid" "$N"
- [ -n "$owe_transition_ifname" ] && append bss_conf "owe_transition_ifname=$owe_transition_ifname" "$N"
-
- wps_possible=1
- # Here we make the assumption that if we're in open mode
- # with WPS enabled, we got to be in unconfigured state.
- wps_not_configured=1
- ;;
- psk|sae|psk-sae)
- json_get_vars key wpa_psk_file
- if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
- json_get_vars auth_secret auth_port
- set_default auth_port 1812
- json_for_each_item append_auth_server auth_server
- append bss_conf "macaddr_acl=2" "$N"
- append bss_conf "wpa_psk_radius=2" "$N"
- elif [ ${#key} -eq 64 ]; then
- append bss_conf "wpa_psk=$key" "$N"
- elif [ ${#key} -ge 8 ] && [ ${#key} -le 63 ]; then
- append bss_conf "wpa_passphrase=$key" "$N"
- elif [ -n "$key" ] || [ -z "$wpa_psk_file" ]; then
- wireless_setup_vif_failed INVALID_WPA_PSK
- return 1
- fi
- [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk
- [ -n "$wpa_psk_file" ] && {
- [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file"
- append bss_conf "wpa_psk_file=$wpa_psk_file" "$N"
- }
- [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N"
-
- set_default dynamic_vlan 0
- vlan_possible=1
- wps_possible=1
- ;;
- eap|eap2|eap-eap2|eap192)
- json_get_vars \
- auth_server auth_secret auth_port \
- dae_client dae_secret dae_port \
- dynamic_ownip ownip radius_client_addr \
- eap_reauth_period request_cui \
- erp_domain mobility_domain \
- fils_realm fils_dhcp
-
- # radius can provide VLAN ID for clients
- vlan_possible=1
-
- set_default dynamic_ownip 1
-
- # legacy compatibility
- [ -n "$auth_server" ] || json_get_var auth_server server
- [ -n "$auth_port" ] || json_get_var auth_port port
- [ -n "$auth_secret" ] || json_get_var auth_secret key
-
- [ "$fils" -gt 0 ] && {
- set_default erp_domain "$mobility_domain"
- set_default erp_domain "$(echo "$ssid" | md5sum | head -c 8)"
- set_default fils_realm "$erp_domain"
-
- append bss_conf "erp_send_reauth_start=1" "$N"
- append bss_conf "erp_domain=$erp_domain" "$N"
- append bss_conf "fils_realm=$fils_realm" "$N"
- append bss_conf "fils_cache_id=$(echo "$fils_realm" | md5sum | head -c 4)" "$N"
-
- [ "$fils_dhcp" = "*" ] && {
- json_get_values network network
- fils_dhcp=
- for net in $network; do
- fils_dhcp="$(ifstatus "$net" | jsonfilter -e '@.data.dhcpserver')"
- [ -n "$fils_dhcp" ] && break
- done
-
- [ -z "$fils_dhcp" -a -n "$network_bridge" -a -n "$network_ifname" ] && \
- fils_dhcp="$(udhcpc -B -n -q -s /lib/netifd/dhcp-get-server.sh -t 1 -i "$network_ifname" 2>/dev/null)"
- }
- [ -n "$fils_dhcp" ] && append bss_conf "dhcp_server=$fils_dhcp" "$N"
- }
-
- set_default auth_port 1812
- set_default dae_port 3799
- set_default request_cui 0
-
- [ "$eap_server" -eq 0 ] && json_for_each_item append_auth_server auth_server
- [ "$request_cui" -gt 0 ] && append bss_conf "radius_request_cui=$request_cui" "$N"
- [ -n "$eap_reauth_period" ] && append bss_conf "eap_reauth_period=$eap_reauth_period" "$N"
-
- [ -n "$dae_client" -a -n "$dae_secret" ] && {
- append bss_conf "radius_das_port=$dae_port" "$N"
- append bss_conf "radius_das_client=$dae_client $dae_secret" "$N"
- }
- json_for_each_item append_radius_auth_req_attr radius_auth_req_attr
-
- if [ -n "$ownip" ]; then
- append bss_conf "own_ip_addr=$ownip" "$N"
- elif [ "$dynamic_ownip" -gt 0 ]; then
- append bss_conf "dynamic_own_ip_addr=$dynamic_ownip" "$N"
- fi
-
- [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
- append bss_conf "eapol_key_index_workaround=1" "$N"
- append bss_conf "ieee8021x=1" "$N"
-
- [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N"
- ;;
- wep)
- local wep_keyidx=0
- json_get_vars key
- hostapd_append_wep_key bss_conf
- append bss_conf "wep_default_key=$wep_keyidx" "$N"
- [ -n "$wep_rekey" ] && append bss_conf "wep_rekey_period=$wep_rekey" "$N"
- ;;
- esac
-
- case "$auth_type" in
- none|owe|psk|sae|psk-sae|wep)
- json_get_vars \
- auth_server auth_port auth_secret \
- ownip radius_client_addr
-
- [ -n "$auth_server" ] && {
- set_default auth_port 1812
-
- json_for_each_item append_auth_server auth_server
- [ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N"
- [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
- append bss_conf "macaddr_acl=2" "$N"
- }
- ;;
- esac
-
- local auth_algs="$((($auth_mode_shared << 1) | $auth_mode_open))"
- append bss_conf "auth_algs=${auth_algs:-1}" "$N"
- append bss_conf "wpa=$wpa" "$N"
- [ -n "$wpa_pairwise" ] && append bss_conf "wpa_pairwise=$wpa_pairwise" "$N"
-
- set_default wps_pushbutton 0
- set_default wps_label 0
- set_default wps_pbc_in_m1 0
-
- config_methods=
- [ "$wps_pushbutton" -gt 0 ] && append config_methods push_button
- [ "$wps_label" -gt 0 ] && append config_methods label
-
- # WPS not possible on Multi-AP backhaul-only SSID
- [ "$multi_ap" = 1 ] && wps_possible=
-
- [ -n "$wps_possible" -a -n "$config_methods" ] && {
- set_default ext_registrar 0
- set_default wps_device_type "6-0050F204-1"
- set_default wps_device_name "OpenWrt AP"
- set_default wps_manufacturer "www.openwrt.org"
- set_default wps_independent 1
-
- wps_state=2
- [ -n "$wps_not_configured" ] && wps_state=1
-
- [ "$ext_registrar" -gt 0 -a -n "$network_bridge" ] && append bss_conf "upnp_iface=$network_bridge" "$N"
-
- append bss_conf "eap_server=1" "$N"
- [ -n "$wps_pin" ] && append bss_conf "ap_pin=$wps_pin" "$N"
- append bss_conf "wps_state=$wps_state" "$N"
- append bss_conf "device_type=$wps_device_type" "$N"
- append bss_conf "device_name=$wps_device_name" "$N"
- append bss_conf "manufacturer=$wps_manufacturer" "$N"
- append bss_conf "config_methods=$config_methods" "$N"
- append bss_conf "wps_independent=$wps_independent" "$N"
- [ -n "$wps_ap_setup_locked" ] && append bss_conf "ap_setup_locked=$wps_ap_setup_locked" "$N"
- [ "$wps_pbc_in_m1" -gt 0 ] && append bss_conf "pbc_in_m1=$wps_pbc_in_m1" "$N"
- [ "$multi_ap" -gt 0 ] && [ -n "$multi_ap_backhaul_ssid" ] && {
- append bss_conf "multi_ap_backhaul_ssid=\"$multi_ap_backhaul_ssid\"" "$N"
- if [ -z "$multi_ap_backhaul_key" ]; then
- :
- elif [ ${#multi_ap_backhaul_key} -lt 8 ]; then
- wireless_setup_vif_failed INVALID_WPA_PSK
- return 1
- elif [ ${#multi_ap_backhaul_key} -eq 64 ]; then
- append bss_conf "multi_ap_backhaul_wpa_psk=$multi_ap_backhaul_key" "$N"
- else
- append bss_conf "multi_ap_backhaul_wpa_passphrase=$multi_ap_backhaul_key" "$N"
- fi
- }
- }
-
- append bss_conf "ssid=$ssid" "$N"
- [ -n "$network_bridge" ] && append bss_conf "bridge=$network_bridge${N}wds_bridge=" "$N"
- [ -n "$network_ifname" ] && append bss_conf "snoop_iface=$network_ifname" "$N"
- [ -n "$iapp_interface" ] && {
- local ifname
- network_get_device ifname "$iapp_interface" || ifname="$iapp_interface"
- append bss_conf "iapp_interface=$ifname" "$N"
- }
-
- json_get_vars time_advertisement time_zone wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo
- set_default bss_transition 0
- set_default wnm_sleep_mode 0
- set_default wnm_sleep_mode_no_keys 0
- set_default mbo 0
-
- [ -n "$time_advertisement" ] && append bss_conf "time_advertisement=$time_advertisement" "$N"
- [ -n "$time_zone" ] && append bss_conf "time_zone=$time_zone" "$N"
- if [ "$wnm_sleep_mode" -eq "1" ]; then
- append bss_conf "wnm_sleep_mode=1" "$N"
- [ "$wnm_sleep_mode_no_keys" -eq "1" ] && append bss_conf "wnm_sleep_mode_no_keys=1" "$N"
- fi
- [ "$bss_transition" -eq "1" ] && append bss_conf "bss_transition=1" "$N"
- [ "$mbo" -eq 1 ] && append bss_conf "mbo=1" "$N"
-
- json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report rnr
- set_default ieee80211k 0
- set_default rnr 0
- if [ "$ieee80211k" -eq "1" ]; then
- set_default rrm_neighbor_report 1
- set_default rrm_beacon_report 1
- else
- set_default rrm_neighbor_report 0
- set_default rrm_beacon_report 0
- fi
-
- [ "$rrm_neighbor_report" -eq "1" ] && append bss_conf "rrm_neighbor_report=1" "$N"
- [ "$rrm_beacon_report" -eq "1" ] && append bss_conf "rrm_beacon_report=1" "$N"
- [ "$rnr" -eq "1" ] && append bss_conf "rnr=1" "$N"
-
- json_get_vars ftm_responder stationary_ap lci civic
- set_default ftm_responder 0
- if [ "$ftm_responder" -eq "1" ]; then
- set_default stationary_ap 0
- iw phy "$phy" info | grep -q "ENABLE_FTM_RESPONDER" && {
- append bss_conf "ftm_responder=1" "$N"
- [ "$stationary_ap" -eq "1" ] && append bss_conf "stationary_ap=1" "$N"
- [ -n "$lci" ] && append bss_conf "lci=$lci" "$N"
- [ -n "$civic" ] && append bss_conf "civic=$civic" "$N"
- }
- fi
-
- json_get_vars ieee80211r
- set_default ieee80211r 0
- if [ "$wpa" -ge "1" ]; then
- if [ "$fils" -gt 0 ]; then
- json_get_vars fils_realm
- set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)"
- fi
-
- append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N"
-
- hostapd_append_wpa_key_mgmt
- [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N"
- fi
-
- if [ "$wpa" -ge "2" ]; then
- if [ "$ieee80211r" -gt "0" ]; then
- json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline
-
- set_default mobility_domain "$(echo "$ssid" | md5sum | head -c 4)"
- set_default ft_over_ds 0
- set_default reassociation_deadline 1000
-
- case "$auth_type" in
- psk)
- set_default ft_psk_generate_local 1
- ;;
- *)
- set_default ft_psk_generate_local 0
- ;;
- esac
-
- [ -n "$network_ifname" ] && append bss_conf "ft_iface=$network_ifname" "$N"
- append bss_conf "mobility_domain=$mobility_domain" "$N"
- append bss_conf "ft_psk_generate_local=$ft_psk_generate_local" "$N"
- append bss_conf "ft_over_ds=$ft_over_ds" "$N"
- append bss_conf "reassociation_deadline=$reassociation_deadline" "$N"
-
- if [ "$ft_psk_generate_local" -eq "0" ]; then
- json_get_vars r0_key_lifetime r1_key_holder pmk_r1_push
- json_get_values r0kh r0kh
- json_get_values r1kh r1kh
-
- set_default r0_key_lifetime 10000
- set_default pmk_r1_push 0
-
- [ -n "$r0kh" -a -n "$r1kh" ] || {
- if [ -z "$auth_secret" -a -z "$key" ]; then
- wireless_setup_vif_failed FT_KEY_CANT_BE_DERIVED
- return 1
- fi
- ft_key=`echo -n "$mobility_domain/${auth_secret:-${key}}" | md5sum | awk '{print $1}'`
-
- set_default r0kh "ff:ff:ff:ff:ff:ff,*,$ft_key"
- set_default r1kh "00:00:00:00:00:00,00:00:00:00:00:00,$ft_key"
- }
-
- [ -n "$r1_key_holder" ] && append bss_conf "r1_key_holder=$r1_key_holder" "$N"
- append bss_conf "r0_key_lifetime=$r0_key_lifetime" "$N"
- append bss_conf "pmk_r1_push=$pmk_r1_push" "$N"
-
- for kh in $r0kh; do
- append bss_conf "r0kh=${kh//,/ }" "$N"
- done
- for kh in $r1kh; do
- append bss_conf "r1kh=${kh//,/ }" "$N"
- done
- fi
- fi
-
- if [ -n "$network_bridge" -a "$rsn_preauth" = 1 ]; then
- set_default auth_cache 1
- append bss_conf "rsn_preauth=1" "$N"
- append bss_conf "rsn_preauth_interfaces=$network_bridge" "$N"
- else
- case "$auth_type" in
- sae|psk-sae|owe)
- set_default auth_cache 1
- ;;
- *)
- set_default auth_cache 0
- ;;
- esac
- fi
-
- append bss_conf "okc=$auth_cache" "$N"
- [ "$auth_cache" = 0 -a "$fils" = 0 ] && append bss_conf "disable_pmksa_caching=1" "$N"
-
- # RSN -> allow management frame protection
- case "$ieee80211w" in
- [012])
- json_get_vars ieee80211w_mgmt_cipher ieee80211w_max_timeout ieee80211w_retry_timeout
- append bss_conf "ieee80211w=$ieee80211w" "$N"
- [ "$ieee80211w" -gt "0" ] && {
- if [ "$auth_type" = "eap192" ]; then
- append bss_conf "group_mgmt_cipher=BIP-GMAC-256" "$N"
- else
- append bss_conf "group_mgmt_cipher=${ieee80211w_mgmt_cipher:-AES-128-CMAC}" "$N"
- fi
- [ -n "$ieee80211w_max_timeout" ] && \
- append bss_conf "assoc_sa_query_max_timeout=$ieee80211w_max_timeout" "$N"
- [ -n "$ieee80211w_retry_timeout" ] && \
- append bss_conf "assoc_sa_query_retry_timeout=$ieee80211w_retry_timeout" "$N"
- }
- ;;
- esac
- fi
-
- _macfile="/var/run/hostapd-$ifname.maclist"
- case "$macfilter" in
- allow)
- append bss_conf "macaddr_acl=1" "$N"
- append bss_conf "accept_mac_file=$_macfile" "$N"
- # accept_mac_file can be used to set MAC to VLAN ID mapping
- vlan_possible=1
- ;;
- deny)
- append bss_conf "macaddr_acl=0" "$N"
- append bss_conf "deny_mac_file=$_macfile" "$N"
- ;;
- *)
- _macfile=""
- ;;
- esac
-
- [ -n "$_macfile" ] && {
- json_get_vars macfile
- json_get_values maclist maclist
-
- rm -f "$_macfile"
- (
- for mac in $maclist; do
- echo "$mac"
- done
- [ -n "$macfile" -a -f "$macfile" ] && cat "$macfile"
- ) > "$_macfile"
- }
-
- [ -n "$vlan_possible" -a -n "$dynamic_vlan" ] && {
- json_get_vars vlan_naming vlan_tagged_interface vlan_bridge vlan_file vlan_no_bridge
- set_default vlan_naming 1
- [ -z "$vlan_file" ] && set_default vlan_file /var/run/hostapd-$ifname.vlan
- append bss_conf "dynamic_vlan=$dynamic_vlan" "$N"
- append bss_conf "vlan_naming=$vlan_naming" "$N"
- if [ -n "$vlan_bridge" ]; then
- append bss_conf "vlan_bridge=$vlan_bridge" "$N"
- else
- set_default vlan_no_bridge 1
- fi
- append bss_conf "vlan_no_bridge=$vlan_no_bridge" "$N"
- [ -n "$vlan_tagged_interface" ] && \
- append bss_conf "vlan_tagged_interface=$vlan_tagged_interface" "$N"
- [ -n "$vlan_file" ] && {
- [ -e "$vlan_file" ] || touch "$vlan_file"
- append bss_conf "vlan_file=$vlan_file" "$N"
- }
- }
-
- json_get_vars iw_enabled iw_internet iw_asra iw_esr iw_uesa iw_access_network_type
- json_get_vars iw_hessid iw_venue_group iw_venue_type iw_network_auth_type
- json_get_vars iw_roaming_consortium iw_domain_name iw_anqp_3gpp_cell_net iw_nai_realm
- json_get_vars iw_anqp_elem iw_qos_map_set iw_ipaddr_type_availability iw_gas_address3
- json_get_vars iw_venue_name iw_venue_url
-
- set_default iw_enabled 0
- if [ "$iw_enabled" = "1" ]; then
- append bss_conf "interworking=1" "$N"
- set_default iw_internet 1
- set_default iw_asra 0
- set_default iw_esr 0
- set_default iw_uesa 0
-
- append bss_conf "internet=$iw_internet" "$N"
- append bss_conf "asra=$iw_asra" "$N"
- append bss_conf "esr=$iw_esr" "$N"
- append bss_conf "uesa=$iw_uesa" "$N"
-
- [ -n "$iw_access_network_type" ] && \
- append bss_conf "access_network_type=$iw_access_network_type" "$N"
- [ -n "$iw_hessid" ] && append bss_conf "hessid=$iw_hessid" "$N"
- [ -n "$iw_venue_group" ] && \
- append bss_conf "venue_group=$iw_venue_group" "$N"
- [ -n "$iw_venue_type" ] && append bss_conf "venue_type=$iw_venue_type" "$N"
- [ -n "$iw_network_auth_type" ] && \
- append bss_conf "network_auth_type=$iw_network_auth_type" "$N"
- [ -n "$iw_gas_address3" ] && append bss_conf "gas_address3=$iw_gas_address3" "$N"
-
- json_for_each_item append_iw_roaming_consortium iw_roaming_consortium
- json_for_each_item append_iw_anqp_elem iw_anqp_elem
- json_for_each_item append_iw_nai_realm iw_nai_realm
- json_for_each_item append_iw_venue_name iw_venue_name
- json_for_each_item append_iw_venue_url iw_venue_url
-
- iw_domain_name_conf=
- json_for_each_item append_iw_domain_name iw_domain_name
- [ -n "$iw_domain_name_conf" ] && \
- append bss_conf "domain_name=$iw_domain_name_conf" "$N"
-
- iw_anqp_3gpp_cell_net_conf=
- json_for_each_item append_iw_anqp_3gpp_cell_net iw_anqp_3gpp_cell_net
- [ -n "$iw_anqp_3gpp_cell_net_conf" ] && \
- append bss_conf "anqp_3gpp_cell_net=$iw_anqp_3gpp_cell_net_conf" "$N"
- fi
-
- set_default iw_qos_map_set 0,0,2,16,1,1,255,255,18,22,24,38,40,40,44,46,48,56
- case "$iw_qos_map_set" in
- *,*);;
- *) iw_qos_map_set="";;
- esac
- [ -n "$iw_qos_map_set" ] && append bss_conf "qos_map_set=$iw_qos_map_set" "$N"
-
- local hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
- osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
- hs20_t_c_server_url
- json_get_vars hs20 disable_dgaf osen anqp_domain_id hs20_deauth_req_timeout \
- osu_ssid hs20_wan_metrics hs20_operating_class hs20_t_c_filename hs20_t_c_timestamp \
- hs20_t_c_server_url
-
- set_default hs20 0
- set_default disable_dgaf $hs20
- set_default osen 0
- set_default anqp_domain_id 0
- set_default hs20_deauth_req_timeout 60
- if [ "$hs20" = "1" ]; then
- append bss_conf "hs20=1" "$N"
- append_hs20_icons
- append bss_conf "disable_dgaf=$disable_dgaf" "$N"
- append bss_conf "osen=$osen" "$N"
- append bss_conf "anqp_domain_id=$anqp_domain_id" "$N"
- append bss_conf "hs20_deauth_req_timeout=$hs20_deauth_req_timeout" "$N"
- [ -n "$osu_ssid" ] && append bss_conf "osu_ssid=$osu_ssid" "$N"
- [ -n "$hs20_wan_metrics" ] && append bss_conf "hs20_wan_metrics=$hs20_wan_metrics" "$N"
- [ -n "$hs20_operating_class" ] && append bss_conf "hs20_operating_class=$hs20_operating_class" "$N"
- [ -n "$hs20_t_c_filename" ] && append bss_conf "hs20_t_c_filename=$hs20_t_c_filename" "$N"
- [ -n "$hs20_t_c_timestamp" ] && append bss_conf "hs20_t_c_timestamp=$hs20_t_c_timestamp" "$N"
- [ -n "$hs20_t_c_server_url" ] && append bss_conf "hs20_t_c_server_url=$hs20_t_c_server_url" "$N"
- json_for_each_item append_hs20_oper_friendly_name hs20_oper_friendly_name
- json_for_each_item append_hs20_conn_capab hs20_conn_capab
- json_for_each_item append_osu_provider osu_provider
- json_for_each_item append_operator_icon operator_icon
- fi
-
- if [ "$eap_server" = "1" ]; then
- append bss_conf "eap_server=1" "$N"
- append bss_conf "eap_server_erp=1" "$N"
- [ -n "$eap_user_file" ] && append bss_conf "eap_user_file=$eap_user_file" "$N"
- [ -n "$ca_cert" ] && append bss_conf "ca_cert=$ca_cert" "$N"
- [ -n "$server_cert" ] && append bss_conf "server_cert=$server_cert" "$N"
- [ -n "$private_key" ] && append bss_conf "private_key=$private_key" "$N"
- [ -n "$private_key_passwd" ] && append bss_conf "private_key_passwd=$private_key_passwd" "$N"
- [ -n "$server_id" ] && append bss_conf "server_id=$server_id" "$N"
- fi
-
- set_default multicast_to_unicast_all 0
- if [ "$multicast_to_unicast_all" -gt 0 ]; then
- append bss_conf "multicast_to_unicast=$multicast_to_unicast_all" "$N"
- fi
- set_default proxy_arp 0
- if [ "$proxy_arp" -gt 0 ]; then
- append bss_conf "proxy_arp=$proxy_arp" "$N"
- fi
-
- set_default per_sta_vif 0
- if [ "$per_sta_vif" -gt 0 ]; then
- append bss_conf "per_sta_vif=$per_sta_vif" "$N"
- fi
-
- json_get_values opts hostapd_bss_options
- for val in $opts; do
- append bss_conf "$val" "$N"
- done
-
- append "$var" "$bss_conf" "$N"
- return 0
-}
-
-hostapd_set_log_options() {
- local var="$1"
-
- local log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
- json_get_vars log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
-
- set_default log_level 2
- set_default log_80211 1
- set_default log_8021x 1
- set_default log_radius 1
- set_default log_wpa 1
- set_default log_driver 1
- set_default log_iapp 1
- set_default log_mlme 1
-
- local log_mask="$(( \
- ($log_80211 << 0) | \
- ($log_8021x << 1) | \
- ($log_radius << 2) | \
- ($log_wpa << 3) | \
- ($log_driver << 4) | \
- ($log_iapp << 5) | \
- ($log_mlme << 6) \
- ))"
-
- append "$var" "logger_syslog=$log_mask" "$N"
- append "$var" "logger_syslog_level=$log_level" "$N"
- append "$var" "logger_stdout=$log_mask" "$N"
- append "$var" "logger_stdout_level=$log_level" "$N"
-
- return 0
-}
-
-_wpa_supplicant_common() {
- local ifname="$1"
-
- _rpath="/var/run/wpa_supplicant"
- _config="${_rpath}-$ifname.conf"
-}
-
-wpa_supplicant_teardown_interface() {
- _wpa_supplicant_common "$1"
- rm -rf "$_rpath/$1" "$_config"
-}
-
-wpa_supplicant_prepare_interface() {
- local ifname="$1"
- _w_driver="$2"
-
- _wpa_supplicant_common "$1"
-
- json_get_vars mode wds multi_ap
-
- [ -n "$network_bridge" ] && {
- fail=
- case "$mode" in
- adhoc)
- fail=1
- ;;
- sta)
- [ "$wds" = 1 -o "$multi_ap" = 1 ] || fail=1
- ;;
- esac
-
- [ -n "$fail" ] && {
- wireless_setup_vif_failed BRIDGE_NOT_ALLOWED
- return 1
- }
- }
-
- local ap_scan=
-
- _w_mode="$mode"
-
- [ "$mode" = adhoc ] && {
- ap_scan="ap_scan=2"
- }
-
- local country_str=
- [ -n "$country" ] && {
- country_str="country=$country"
- }
-
- multiap_flag_file="${_config}.is_multiap"
- if [ "$multi_ap" = "1" ]; then
- touch "$multiap_flag_file"
- else
- [ -e "$multiap_flag_file" ] && rm "$multiap_flag_file"
- fi
- wpa_supplicant_teardown_interface "$ifname"
- cat > "$_config" <<EOF
-${scan_list:+freq_list=$scan_list}
-$ap_scan
-$country_str
-EOF
- return 0
-}
-
-wpa_supplicant_set_fixed_freq() {
- local freq="$1"
- local htmode="$2"
-
- append network_data "fixed_freq=1" "$N$T"
- append network_data "frequency=$freq" "$N$T"
- case "$htmode" in
- NOHT) append network_data "disable_ht=1" "$N$T";;
- HE20|HT20|VHT20) append network_data "disable_ht40=1" "$N$T";;
- HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160) append network_data "ht40=1" "$N$T";;
- esac
- case "$htmode" in
- VHT*) append network_data "vht=1" "$N$T";;
- esac
- case "$htmode" in
- HE80|VHT80) append network_data "max_oper_chwidth=1" "$N$T";;
- HE160|VHT160) append network_data "max_oper_chwidth=2" "$N$T";;
- HE20|HE40|VHT20|VHT40) append network_data "max_oper_chwidth=0" "$N$T";;
- *) append network_data "disable_vht=1" "$N$T";;
- esac
-}
-
-wpa_supplicant_add_network() {
- local ifname="$1"
- local freq="$2"
- local htmode="$3"
- local noscan="$4"
-
- _wpa_supplicant_common "$1"
- wireless_vif_parse_encryption
-
- json_get_vars \
- ssid bssid key \
- basic_rate mcast_rate \
- ieee80211w ieee80211r fils ocv \
- multi_ap \
- default_disabled
-
- case "$auth_type" in
- sae|owe|eap2|eap192)
- set_default ieee80211w 2
- ;;
- psk-sae)
- set_default ieee80211w 1
- ;;
- esac
-
- set_default ieee80211r 0
- set_default multi_ap 0
- set_default default_disabled 0
-
- local key_mgmt='NONE'
- local network_data=
- local T=" "
-
- local scan_ssid="scan_ssid=1"
- local freq wpa_key_mgmt
-
- [ "$_w_mode" = "adhoc" ] && {
- append network_data "mode=1" "$N$T"
- [ -n "$freq" ] && wpa_supplicant_set_fixed_freq "$freq" "$htmode"
- [ "$noscan" = "1" ] && append network_data "noscan=1" "$N$T"
-
- scan_ssid="scan_ssid=0"
-
- [ "$_w_driver" = "nl80211" ] || append wpa_key_mgmt "WPA-NONE"
- }
-
- [ "$_w_mode" = "mesh" ] && {
- json_get_vars mesh_id mesh_fwding mesh_rssi_threshold encryption
- [ -n "$mesh_id" ] && ssid="${mesh_id}"
-
- append network_data "mode=5" "$N$T"
- [ -n "$mesh_fwding" ] && append network_data "mesh_fwding=${mesh_fwding}" "$N$T"
- [ -n "$mesh_rssi_threshold" ] && append network_data "mesh_rssi_threshold=${mesh_rssi_threshold}" "$N$T"
- [ -n "$freq" ] && wpa_supplicant_set_fixed_freq "$freq" "$htmode"
- [ "$noscan" = "1" ] && append network_data "noscan=1" "$N$T"
- [ "$encryption" = "none" -o -z "$encryption" ] || append wpa_key_mgmt "SAE"
- scan_ssid=""
- }
-
- [ "$_w_mode" = "sta" ] && {
- [ "$multi_ap" = 1 ] && append network_data "multi_ap_backhaul_sta=1" "$N$T"
- [ "$default_disabled" = 1 ] && append network_data "disabled=1" "$N$T"
- }
-
- [ -n "$ocv" ] && append network_data "ocv=$ocv" "$N$T"
-
- case "$auth_type" in
- none) ;;
- owe)
- hostapd_append_wpa_key_mgmt
- key_mgmt="$wpa_key_mgmt"
- ;;
- wep)
- local wep_keyidx=0
- hostapd_append_wep_key network_data
- append network_data "wep_tx_keyidx=$wep_keyidx" "$N$T"
- ;;
- wps)
- key_mgmt='WPS'
- ;;
- psk|sae|psk-sae)
- local passphrase
-
- if [ "$_w_mode" != "mesh" ]; then
- hostapd_append_wpa_key_mgmt
- fi
-
- key_mgmt="$wpa_key_mgmt"
-
- if [ "$_w_mode" = "mesh" ] || [ "$auth_type" = "sae" ]; then
- passphrase="sae_password=\"${key}\""
- else
- if [ ${#key} -eq 64 ]; then
- passphrase="psk=${key}"
- else
- passphrase="psk=\"${key}\""
- fi
- fi
- append network_data "$passphrase" "$N$T"
- ;;
- eap|eap2|eap192)
- hostapd_append_wpa_key_mgmt
- key_mgmt="$wpa_key_mgmt"
-
- json_get_vars eap_type identity anonymous_identity ca_cert ca_cert_usesystem
-
- [ "$fils" -gt 0 ] && append network_data "erp=1" "$N$T"
- if [ "$ca_cert_usesystem" -eq "1" -a -f "/etc/ssl/certs/ca-certificates.crt" ]; then
- append network_data "ca_cert=\"/etc/ssl/certs/ca-certificates.crt\"" "$N$T"
- else
- [ -n "$ca_cert" ] && append network_data "ca_cert=\"$ca_cert\"" "$N$T"
- fi
- [ -n "$identity" ] && append network_data "identity=\"$identity\"" "$N$T"
- [ -n "$anonymous_identity" ] && append network_data "anonymous_identity=\"$anonymous_identity\"" "$N$T"
- case "$eap_type" in
- tls)
- json_get_vars client_cert priv_key priv_key_pwd
- append network_data "client_cert=\"$client_cert\"" "$N$T"
- append network_data "private_key=\"$priv_key\"" "$N$T"
- append network_data "private_key_passwd=\"$priv_key_pwd\"" "$N$T"
-
- json_get_vars subject_match
- [ -n "$subject_match" ] && append network_data "subject_match=\"$subject_match\"" "$N$T"
-
- json_get_values altsubject_match altsubject_match
- if [ -n "$altsubject_match" ]; then
- local list=
- for x in $altsubject_match; do
- append list "$x" ";"
- done
- append network_data "altsubject_match=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_match domain_match
- if [ -n "$domain_match" ]; then
- local list=
- for x in $domain_match; do
- append list "$x" ";"
- done
- append network_data "domain_match=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_suffix_match domain_suffix_match
- if [ -n "$domain_suffix_match" ]; then
- local list=
- for x in $domain_suffix_match; do
- append list "$x" ";"
- done
- append network_data "domain_suffix_match=\"$list\"" "$N$T"
- fi
- ;;
- fast|peap|ttls)
- json_get_vars auth password ca_cert2 ca_cert2_usesystem client_cert2 priv_key2 priv_key2_pwd
- set_default auth MSCHAPV2
-
- if [ "$auth" = "EAP-TLS" ]; then
- if [ "$ca_cert2_usesystem" -eq "1" -a -f "/etc/ssl/certs/ca-certificates.crt" ]; then
- append network_data "ca_cert2=\"/etc/ssl/certs/ca-certificates.crt\"" "$N$T"
- else
- [ -n "$ca_cert2" ] && append network_data "ca_cert2=\"$ca_cert2\"" "$N$T"
- fi
- append network_data "client_cert2=\"$client_cert2\"" "$N$T"
- append network_data "private_key2=\"$priv_key2\"" "$N$T"
- append network_data "private_key2_passwd=\"$priv_key2_pwd\"" "$N$T"
- else
- append network_data "password=\"$password\"" "$N$T"
- fi
-
- json_get_vars subject_match
- [ -n "$subject_match" ] && append network_data "subject_match=\"$subject_match\"" "$N$T"
-
- json_get_values altsubject_match altsubject_match
- if [ -n "$altsubject_match" ]; then
- local list=
- for x in $altsubject_match; do
- append list "$x" ";"
- done
- append network_data "altsubject_match=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_match domain_match
- if [ -n "$domain_match" ]; then
- local list=
- for x in $domain_match; do
- append list "$x" ";"
- done
- append network_data "domain_match=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_suffix_match domain_suffix_match
- if [ -n "$domain_suffix_match" ]; then
- local list=
- for x in $domain_suffix_match; do
- append list "$x" ";"
- done
- append network_data "domain_suffix_match=\"$list\"" "$N$T"
- fi
-
- phase2proto="auth="
- case "$auth" in
- "auth"*)
- phase2proto=""
- ;;
- "EAP-"*)
- auth="$(echo $auth | cut -b 5- )"
- [ "$eap_type" = "ttls" ] &&
- phase2proto="autheap="
- json_get_vars subject_match2
- [ -n "$subject_match2" ] && append network_data "subject_match2=\"$subject_match2\"" "$N$T"
-
- json_get_values altsubject_match2 altsubject_match2
- if [ -n "$altsubject_match2" ]; then
- local list=
- for x in $altsubject_match2; do
- append list "$x" ";"
- done
- append network_data "altsubject_match2=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_match2 domain_match2
- if [ -n "$domain_match2" ]; then
- local list=
- for x in $domain_match2; do
- append list "$x" ";"
- done
- append network_data "domain_match2=\"$list\"" "$N$T"
- fi
-
- json_get_values domain_suffix_match2 domain_suffix_match2
- if [ -n "$domain_suffix_match2" ]; then
- local list=
- for x in $domain_suffix_match2; do
- append list "$x" ";"
- done
- append network_data "domain_suffix_match2=\"$list\"" "$N$T"
- fi
- ;;
- esac
- append network_data "phase2=\"$phase2proto$auth\"" "$N$T"
- ;;
- esac
- append network_data "eap=$(echo $eap_type | tr 'a-z' 'A-Z')" "$N$T"
- ;;
- esac
-
- [ "$wpa_cipher" = GCMP ] && {
- append network_data "pairwise=GCMP" "$N$T"
- append network_data "group=GCMP" "$N$T"
- }
-
- [ "$mode" = mesh ] || {
- case "$wpa" in
- 1)
- append network_data "proto=WPA" "$N$T"
- ;;
- 2)
- append network_data "proto=RSN" "$N$T"
- ;;
- esac
-
- case "$ieee80211w" in
- [012])
- [ "$wpa" -ge 2 ] && append network_data "ieee80211w=$ieee80211w" "$N$T"
- ;;
- esac
- }
- [ -n "$bssid" ] && append network_data "bssid=$bssid" "$N$T"
- [ -n "$beacon_int" ] && append network_data "beacon_int=$beacon_int" "$N$T"
-
- local bssid_blacklist bssid_whitelist
- json_get_values bssid_blacklist bssid_blacklist
- json_get_values bssid_whitelist bssid_whitelist
-
- [ -n "$bssid_blacklist" ] && append network_data "bssid_blacklist=$bssid_blacklist" "$N$T"
- [ -n "$bssid_whitelist" ] && append network_data "bssid_whitelist=$bssid_whitelist" "$N$T"
-
- [ -n "$basic_rate" ] && {
- local br rate_list=
- for br in $basic_rate; do
- wpa_supplicant_add_rate rate_list "$br"
- done
- [ -n "$rate_list" ] && append network_data "rates=$rate_list" "$N$T"
- }
-
- [ -n "$mcast_rate" ] && {
- local mc_rate=
- wpa_supplicant_add_rate mc_rate "$mcast_rate"
- append network_data "mcast_rate=$mc_rate" "$N$T"
- }
-
- if [ "$key_mgmt" = "WPS" ]; then
- echo "wps_cred_processing=1" >> "$_config"
- else
- cat >> "$_config" <<EOF
-network={
- $scan_ssid
- ssid="$ssid"
- key_mgmt=$key_mgmt
- $network_data
-}
-EOF
- fi
- return 0
-}
+++ /dev/null
-#!/usr/bin/env ucode
-'use strict';
-import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
-import { readfile, writefile, basename, readlink, glob } from "fs";
-let libubus = require("ubus");
-
-let keep_devices = {};
-let phy = shift(ARGV);
-let command = shift(ARGV);
-let phydev;
-
-function iface_stop(wdev)
-{
- if (keep_devices[wdev.ifname])
- return;
-
- wdev_remove(wdev.ifname);
-}
-
-function iface_start(wdev)
-{
- let ifname = wdev.ifname;
-
- if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
- wdev_set_up(ifname, false);
- wdev_remove(ifname);
- }
- let wdev_config = {};
- for (let key in wdev)
- wdev_config[key] = wdev[key];
- if (!wdev_config.macaddr && wdev.mode != "monitor")
- wdev_config.macaddr = phydev.macaddr_next();
- wdev_create(phy, ifname, wdev_config);
- wdev_set_up(ifname, true);
- if (wdev.freq)
- system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`);
- if (wdev.mode == "adhoc") {
- let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ];
- if (wdev.bssid)
- push(cmd, wdev.bssid);
- for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
- if (wdev[key])
- push(cmd, key, wdev[key]);
- system(cmd);
- } else if (wdev.mode == "mesh") {
- let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, wdev.htmode ];
- for (let key in [ "mcast-rate", "beacon-interval" ])
- if (wdev[key])
- push(cmd, key, wdev[key]);
- system(cmd);
-
- wdev_set_mesh_params(ifname, wdev);
- }
-}
-
-function iface_cb(new_if, old_if)
-{
- if (old_if && new_if && is_equal(old_if, new_if))
- return;
-
- if (old_if)
- iface_stop(old_if);
- if (new_if)
- iface_start(new_if);
-}
-
-function drop_inactive(config)
-{
- for (let key in config) {
- if (!readfile(`/sys/class/net/${key}/ifindex`))
- delete config[key];
- }
-}
-
-function add_ifname(config)
-{
- for (let key in config)
- config[key].ifname = key;
-}
-
-function delete_ifname(config)
-{
- for (let key in config)
- delete config[key].ifname;
-}
-
-function add_existing(phy, config)
-{
- let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
- wdevs = map(wdevs, (arg) => basename(arg));
- for (let wdev in wdevs) {
- if (config[wdev])
- continue;
-
- if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
- continue;
-
- if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
- config[wdev] = {};
- }
-}
-
-function usage()
-{
- warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
-
-Commands:
- set_config <config> [<device]...] - set phy configuration
- get_macaddr <id> - get phy MAC address for vif index <id>
-`);
- exit(1);
-}
-
-const commands = {
- set_config: function(args) {
- let statefile = `/var/run/wdev-${phy}.json`;
-
- let new_config = shift(args);
- for (let dev in ARGV)
- keep_devices[dev] = true;
-
- if (!new_config)
- usage();
-
- new_config = json(new_config);
- if (!new_config) {
- warn("Invalid configuration\n");
- exit(1);
- }
-
- let old_config = readfile(statefile);
- if (old_config)
- old_config = json(old_config);
-
- let config = vlist_new(iface_cb);
- if (type(old_config) == "object")
- config.data = old_config;
-
- add_existing(phy, config.data);
- add_ifname(config.data);
- drop_inactive(config.data);
-
- let ubus = libubus.connect();
- let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
- let macaddr_list = [];
- if (type(data) == "object" && data.macaddr)
- macaddr_list = data.macaddr;
- ubus.disconnect();
- phydev.macaddr_init(macaddr_list);
-
- add_ifname(new_config);
- config.update(new_config);
-
- drop_inactive(config.data);
- delete_ifname(config.data);
- writefile(statefile, sprintf("%J", config.data));
- },
- get_macaddr: function(args) {
- let data = {};
-
- for (let arg in args) {
- arg = split(arg, "=", 2);
- data[arg[0]] = arg[1];
- }
-
- let macaddr = phydev.macaddr_generate(data);
- if (!macaddr) {
- warn(`Could not get MAC address for phy ${phy}\n`);
- exit(1);
- }
-
- print(macaddr + "\n");
- },
-};
-
-if (!phy || !command | !commands[command])
- usage();
-
-phydev = phy_open(phy);
-if (!phydev) {
- warn(`PHY ${phy} does not exist\n`);
- exit(1);
-}
-
-commands[command](ARGV);