mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
Compare commits
33 Commits
v2.11.0-rc
...
v2.11.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd41f15987 | ||
|
|
007cfe9c16 | ||
|
|
52884b2835 | ||
|
|
6a6af16f48 | ||
|
|
2818722b19 | ||
|
|
194eba2d21 | ||
|
|
3d41a22fba | ||
|
|
acd4b79dd4 | ||
|
|
befac1e065 | ||
|
|
7e4e221ccb | ||
|
|
1d9b69ee6f | ||
|
|
018f20119d | ||
|
|
9a6e41adb8 | ||
|
|
970b22856f | ||
|
|
95032994fe | ||
|
|
48cda63dc5 | ||
|
|
8e9f79964a | ||
|
|
3c7df86373 | ||
|
|
38e6aee074 | ||
|
|
0a13684bb6 | ||
|
|
e7ca6e8455 | ||
|
|
f17e635d34 | ||
|
|
90e78c6068 | ||
|
|
550bb6fb7e | ||
|
|
b3a0ebe534 | ||
|
|
6d16e50bbe | ||
|
|
513eec1c5f | ||
|
|
6a797e8a64 | ||
|
|
082134bc43 | ||
|
|
03ec2de777 | ||
|
|
989d39d1f2 | ||
|
|
b6b298ad68 | ||
|
|
be1cb862f1 |
@@ -18,7 +18,7 @@ DEFAULT_PACKAGES += kmod-qca-nss-dp kmod-qca-ssdk swconfig \
|
||||
kmod-usb-phy-ipq807x kmod-usb-dwc3-of-simple \
|
||||
kmod-ath11k-ahb kmod-qrtr_mproc wpad \
|
||||
kmod-gpio-button-hotplug kmod-bootconfig \
|
||||
qca-thermald-10.4 qca-ssdk-shell kmod-qca-nss-drv-bridge-mgr \
|
||||
qca-thermald-10.4 qca-ssdk-shell \
|
||||
uboot-envtools
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@@ -64,8 +64,11 @@ qcom_setup_interfaces()
|
||||
ucidef_set_interface_wan "eth0"
|
||||
;;
|
||||
cig,wf186w)
|
||||
ucidef_add_switch "switch0" "4:wan" "1:lan" "2:lan" "3:lan" "0:lan" "6@eth0"
|
||||
ucidef_add_switch "switch0" "4:wan" "0:lan" "1:lan" "2:lan" "3:lan" "6@eth0"
|
||||
;;
|
||||
cig,wf186h)
|
||||
ucidef_add_switch "switch0" "4:wan" "1:lan" "2:lan" "6@eth0"
|
||||
;;
|
||||
yuncore,fap650)
|
||||
ucidef_set_interface_lan "eth3 eth2 eth1 eth0"
|
||||
ucidef_set_interface_wan "eth4"
|
||||
@@ -180,6 +183,15 @@ qcom_setup_macs()
|
||||
# ip link set eth1 address $wan_mac
|
||||
# ucidef_set_label_macaddr $wan_mac
|
||||
;;
|
||||
cig,wf186h)
|
||||
mtd=$(find_mtd_chardev "0:APPSBLENV")
|
||||
[ -z "$mtd" ] && return;
|
||||
mac=$(grep BaseMacAddress= $mtd | cut -dx -f2)
|
||||
[ -z "$mac" ] && return;
|
||||
wan_mac=$(macaddr_canonicalize $mac)
|
||||
ucidef_set_network_device_mac eth0 $wan_mac
|
||||
ip link set eth0 address $wan_mac
|
||||
;;
|
||||
cybertan,eww631-a1|\
|
||||
cybertan,eww631-b1)
|
||||
mac=$(grep -i -m 1 BaseMacAddress= /dev/`cat /proc/mtd | grep APPSBLENV | cut -d: -f1` | cut -d= -f2)
|
||||
@@ -203,9 +215,10 @@ qcom_setup_macs()
|
||||
ucidef_set_label_macaddr $wan_mac
|
||||
;;
|
||||
cig,wf660a)
|
||||
mmc_dev=$(echo $(find_mmc_part "0:APPSBLENV") | sed 's/^.\{5\}//')
|
||||
[ -z mmc_dev ] && return
|
||||
mac=$(grep BaseMacAddress= /dev/$mmc_dev | cut -dx -f2)
|
||||
mmc_dev=$(find_mtd_chardev "0:APPSBLENV")
|
||||
[ -z "$mmc_dev" ] && mmc_dev=$(find_mmc_part "0:APPSBLENV")
|
||||
[ -z "$mmc_dev" ] && return
|
||||
mac=$(grep BaseMacAddress= $mmc_dev | cut -dx -f2)
|
||||
[ -z "$mac" ] && return;
|
||||
wan_mac=$(macaddr_canonicalize $mac)
|
||||
ucidef_set_network_device_mac eth0 $wan_mac
|
||||
|
||||
@@ -61,8 +61,9 @@ ath11k_generate_macs_pax1800() {
|
||||
|
||||
ath11k_generate_macs_wf660a() {
|
||||
touch /lib/firmware/ath11k-macs
|
||||
mmc_dev=$(find_mmc_part 0:APPSBLENV)
|
||||
[ -n $mmc_dev ] && mac=$(grep BaseMacAddress= $mmc_dev | cut -dx -f2)
|
||||
mmc_dev=$(find_mtd_chardev "0:APPSBLENV")
|
||||
[ -z "$mmc_dev" ] && mmc_dev=$(find_mmc_part "0:APPSBLENV")
|
||||
[ -n "$mmc_dev" ] && mac=$(grep BaseMacAddress= $mmc_dev | cut -dx -f2)
|
||||
eth=$(macaddr_canonicalize $mac)
|
||||
mac1=$(macaddr_add $eth 1)
|
||||
mac2=$(macaddr_add $eth 2)
|
||||
@@ -85,6 +86,19 @@ ath11k_generate_macs_wf186w() {
|
||||
echo -ne \\x${mac3//:/\\x} >> /lib/firmware/ath11k-macs
|
||||
}
|
||||
|
||||
ath11k_generate_macs_wf186h() {
|
||||
touch /lib/firmware/ath11k-macs
|
||||
local dev=$(find_mtd_chardev "0:APPSBLENV")
|
||||
mac=$(grep BaseMacAddress= $dev | cut -dx -f2)
|
||||
eth=$(macaddr_canonicalize $mac)
|
||||
mac1=$(macaddr_add $eth 2)
|
||||
mac2=$(macaddr_add $eth 3)
|
||||
mac3=$(macaddr_add $eth 4)
|
||||
echo -ne \\x${mac1//:/\\x} >> /lib/firmware/ath11k-macs
|
||||
echo -ne \\x${mac2//:/\\x} >> /lib/firmware/ath11k-macs
|
||||
echo -ne \\x${mac3//:/\\x} >> /lib/firmware/ath11k-macs
|
||||
}
|
||||
|
||||
|
||||
caldata_die() {
|
||||
echo "caldata: " "$*"
|
||||
@@ -159,6 +173,7 @@ case "$FIRMWARE" in
|
||||
ath11k/IPQ5018/hw1.0/caldata.bin)
|
||||
case "$board" in
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
cybertan,eww622-a1|\
|
||||
cybertan,eww631-a1|\
|
||||
cybertan,eww631-b1|\
|
||||
@@ -180,6 +195,7 @@ ath11k/IPQ5018/hw1.0/caldata.bin)
|
||||
ath11k/qcn6122/hw1.0/caldata_1.bin)
|
||||
case "$board" in
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
wallys,dr5018|\
|
||||
hfcl,ion4xi_w|\
|
||||
hfcl,ion4x_w|\
|
||||
@@ -269,6 +285,9 @@ ath11k-macs)
|
||||
cig,wf186w)
|
||||
ath11k_generate_macs_wf186w
|
||||
;;
|
||||
cig,wf186h)
|
||||
ath11k_generate_macs_wf186h
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
|
||||
40
feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/net/50-dvlan
Normal file
40
feeds/ipq807x/ipq807x/base-files/etc/hotplug.d/net/50-dvlan
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
debug() {
|
||||
logger -t HOTPLUG-DVLAN "$*"
|
||||
}
|
||||
|
||||
if [ "${INTERFACE:0:4}" != "wlan" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$(board_name)" in
|
||||
"cig,wf186w")
|
||||
wan_iface="eth0"
|
||||
switch_dev="switch0"
|
||||
switch_wan_port=4
|
||||
switch_cpu_port=6
|
||||
;;
|
||||
|
||||
*)
|
||||
exit 0
|
||||
esac
|
||||
|
||||
VSTR="$(echo $INTERFACE | egrep -o 'v([0-9]+)$')"
|
||||
[ -z "$VSTR" ] && exit 0
|
||||
VID="${VSTR:1}"
|
||||
[ $VID -lt 1 -o $VID -gt 4096 ] && exit 0
|
||||
|
||||
if [ "$ACTION" = "add" ]; then
|
||||
debug "[$INTERFACE] Dynamic VLAN $VID added, configuring switch"
|
||||
swconfig dev ${switch_dev} vlan $VID set ports "${switch_wan_port}t ${switch_cpu_port}t"
|
||||
elif [ "$ACTION" = "remove" ]; then
|
||||
let cnt="$(bridge vlan show vid $VID | egrep "^wlan" | wc -l)"
|
||||
debug "[$INTERFACE] Dynamic VLAN interface removed, references left = $cnt"
|
||||
if [ $cnt -eq 0 ]; then
|
||||
debug "[$INTERFACE] No more references, removing $VID from switch"
|
||||
swconfig dev ${switch_dev} vlan $VID set ports ""
|
||||
fi
|
||||
fi
|
||||
@@ -52,7 +52,7 @@ do_flash_emmc() {
|
||||
tar Oxf $tar_file ${board_dir}/$part | dd of=${emmcblock}
|
||||
}
|
||||
|
||||
emmc_do_upgrade_bootconfig() {
|
||||
spi_nor_emmc_do_upgrade_bootconfig() {
|
||||
local tar_file="$1"
|
||||
|
||||
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
|
||||
@@ -84,11 +84,17 @@ emmc_do_upgrade_bootconfig() {
|
||||
fi
|
||||
|
||||
for part in "0:BOOTCONFIG" "0:BOOTCONFIG1"; do
|
||||
local emmcblock=$(find_mmc_part $part)
|
||||
echo erase ${emmcblock}
|
||||
dd if=/dev/zero of=${emmcblock} 2> /dev/null
|
||||
echo update $emmcblock
|
||||
dd if=/tmp/bootconfig of=${emmcblock} 2> /dev/null
|
||||
local mtdchar=$(echo $(find_mtd_chardev $part) | sed 's/^.\{5\}//')
|
||||
if [ -n "$mtdchar" ]; then
|
||||
echo start to update $mtdchar
|
||||
mtd -qq write /proc/boot_info/getbinary_bootconfig "/dev/${mtdchar}" 2>/dev/null && echo update mtd $mtdchar
|
||||
else
|
||||
emmcblock=$(find_mmc_part $part)
|
||||
echo erase ${emmcblock}
|
||||
dd if=/dev/zero of=${emmcblock} 2> /dev/null
|
||||
echo update $emmcblock
|
||||
dd if=/tmp/bootconfig of=${emmcblock} 2> /dev/null
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
@@ -111,6 +117,7 @@ platform_check_image() {
|
||||
board=$(board_name)
|
||||
case $board in
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
cig,wf188|\
|
||||
cig,wf660a|\
|
||||
cig,wf188n|\
|
||||
@@ -174,7 +181,7 @@ platform_do_upgrade() {
|
||||
qca_do_upgrade $1
|
||||
;;
|
||||
cig,wf660a)
|
||||
emmc_do_upgrade_bootconfig $1
|
||||
spi_nor_emmc_do_upgrade_bootconfig $1
|
||||
;;
|
||||
motorola,q14)
|
||||
emmc_do_upgrade $1
|
||||
@@ -267,6 +274,7 @@ platform_do_upgrade() {
|
||||
platform_do_upgrade_dualboot_datachk "$1"
|
||||
;;
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
yuncore,ax840|\
|
||||
yuncore,fap655)
|
||||
[ -f /proc/boot_info/rootfs/upgradepartition ] && {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../../../arm64/boot/dts/qcom/qcom-ipq5018-cig-wf186h.dts"
|
||||
|
||||
/ {
|
||||
pmuv8: pmu {
|
||||
compatible = "arm,cortex-a7-pmu";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,965 @@
|
||||
/dts-v1/;
|
||||
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qcom-ipq5018.dtsi"
|
||||
|
||||
/ {
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
model = "CIG wf186h";
|
||||
compatible = "cig,wf186h","qcom,ipq5018-mp03.3", "qcom,ipq5018";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
aliases {
|
||||
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
|
||||
serial0 = &blsp1_uart1;
|
||||
serial1 = &blsp1_uart2;
|
||||
ethernet0 = "/soc/dp1";
|
||||
ethernet1 = "/soc/dp2";
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,115200,n8 rw init=/init";
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
bootargs-append = " swiotlb=1";
|
||||
#else
|
||||
bootargs-append = " swiotlb=1 coherent_pool=2M";
|
||||
#endif
|
||||
stdout-path = "serial0";
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
/* 256 MB Profile
|
||||
* +=========+==============+========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | NSS | 0x40000000 | 8MB |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Linux | 0x40800000 | Depends on total memory |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* + | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Q6 | 0x4B000000 | 16MB |
|
||||
* | code/ | | |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |IPQ5018 | 0x4C000000 | 13MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4CD00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4CE00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* |QCN6122 | 0x4CF00000 | 15MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4DE00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4DF00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |QCN9000 | 0x4E000000 | 17MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | MHI1 | 0x4F100000 | 16MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +=================================================+
|
||||
*/
|
||||
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x3000000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01000000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4c000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4c000000 0x0 0xD00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4CD00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CD00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region:q6_etr_dump@4CE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4CF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CF00000 0x0 0xF00000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4DE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4DE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4DF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4DF00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn9000_region: qcn9000_pcie0@4E000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E000000 0x0 0x01100000>;
|
||||
};
|
||||
|
||||
mhi_region1: dma_pool1@4F100000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x0 0x4F100000 0x0 0x01000000>;
|
||||
};
|
||||
#elif __IPQ_MEM_PROFILE_512_MB__
|
||||
/* 512 MB Profile
|
||||
* +=========+==============+========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Q6 | 0x4B000000 | 16MB |
|
||||
* | code/ | | |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |IPQ5018 | 0x4C000000 | 14MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4CE00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4CF00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | caldb | 0x4D000000 | 2MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* |QCN6122 | 0x4D200000 | 16MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4E200000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | caldb | 0x4E400000 | 5MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |QCN9000 | 0x4E900000 | 30MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | MHI1 | 0x50700000 | 16MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +=================================================+
|
||||
*/
|
||||
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x3900000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01000000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C000000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4CE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4CF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CF00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D000000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn9000_region: qcn9000_pcie0@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E900000 0x0 0x01E00000>;
|
||||
};
|
||||
|
||||
mhi_region1: dma_pool1@50700000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x0 0x50700000 0x0 0x01000000>;
|
||||
};
|
||||
#else
|
||||
/* 1G Profile
|
||||
* +=========+==============+========================+
|
||||
* | | | |
|
||||
* | Region | Start Offset | Size |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | NSS | 0x40000000 | 16MB |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Linux | 0x41000000 | Depends on total memory |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | uboot | 0x4A600000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | SBL | 0x4AA00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | smem | 0x4AB00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | TZ | 0x4AC00000 | 4MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Q6 | 0x4B000000 | 16MB |
|
||||
* | code/ | | |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |IPQ5018 | 0x4C000000 | 14MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4CE00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4CF00000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | caldb | 0x4D000000 | 2MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* |QCN6122 | 0x4D200000 | 16MB |
|
||||
* | data | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | M3 Dump| 0x4E200000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | QDSS | 0x4E300000 | 1MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | caldb | 0x4E400000 | 5MB |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* |QCN9000 | 0x4E900000 | 45MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | | | |
|
||||
* | MHI1 | 0x51600000 | 24MB |
|
||||
* | | | |
|
||||
* +--------+--------------+-------------------------+
|
||||
* | |
|
||||
* | Rest of the memory for Linux |
|
||||
* | |
|
||||
* +=================================================+
|
||||
*/
|
||||
|
||||
q6_mem_regions: q6_mem_regions@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 0x3900000>;
|
||||
};
|
||||
|
||||
q6_code_data: q6_code_data@4B000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4B000000 0x0 01000000>;
|
||||
};
|
||||
|
||||
q6_ipq5018_data: q6_ipq5018_data@4C000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4C000000 0x0 0xE00000>;
|
||||
};
|
||||
|
||||
m3_dump: m3_dump@4CE00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CE00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_etr_region: q6_etr_dump@4CF00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4CF00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_caldb_region: q6_caldb_region@4D000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D000000 0x0 0x200000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_data1: q6_qcn6122_data1@4D200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4D200000 0x0 0x1000000>;
|
||||
};
|
||||
|
||||
m3_dump_qcn6122_1: m3_dump_qcn6122_1@4E200000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E200000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_etr_1: q6_qcn6122_etr_1@4E300000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E300000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
q6_qcn6122_caldb_1: q6_qcn6122_caldb_1@4E400000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E400000 0x0 0x500000>;
|
||||
};
|
||||
|
||||
q6_qcn9000_region: qcn9000_pcie0@4E900000 {
|
||||
no-map;
|
||||
reg = <0x0 0x4E900000 0x0 0x02D00000>;
|
||||
};
|
||||
|
||||
mhi_region1: dma_pool1@51600000 {
|
||||
compatible = "shared-dma-pool";
|
||||
no-map;
|
||||
reg = <0x0 0x51600000 0x0 0x01800000>;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
soc {
|
||||
serial@78af000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
blsp1_uart2: serial@78b0000 {
|
||||
pinctrl-0 = <&blsp1_uart_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
qpic_bam: dma@7984000{
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
nand: qpic-nand@79b0000 {
|
||||
pinctrl-0 = <&qspi_nand_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
spi_0: spi@78b5000 { /* BLSP1 QUP0 */
|
||||
pinctrl-0 = <&blsp0_spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
cs-select = <0>;
|
||||
status = "ok";
|
||||
|
||||
m25p80@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0>;
|
||||
compatible = "n25q128a11";
|
||||
linux,modalias = "m25p80", "n25q128a11";
|
||||
spi-max-frequency = <50000000>;
|
||||
use-default-sizes;
|
||||
};
|
||||
};
|
||||
|
||||
mdio0: mdio@88000 {
|
||||
status = "ok";
|
||||
ethernet-phy@0 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1: mdio@90000 {
|
||||
status = "ok";
|
||||
pinctrl-0 = <&mdio1_pins>;
|
||||
pinctrl-names = "default";
|
||||
phy-reset-gpio = <&tlmm 35 0>;
|
||||
cig_clk_div = <0xff>;
|
||||
ethernet-phy@0 {
|
||||
reg = <0x1d>;
|
||||
};
|
||||
};
|
||||
|
||||
realtek@29{
|
||||
compatible = "realtek,rtl8367s";
|
||||
mii-bus = <&mdio1>;
|
||||
realtek,extif0 = <0 0 10 1 1 1 1 1 2>;
|
||||
switch = <&tlmm 35 0>;
|
||||
phy-addr = <29>;
|
||||
status = "ok";
|
||||
};
|
||||
ess-instance {
|
||||
num_devices = <0x1>;
|
||||
ess-switch@0x39c00000 {
|
||||
compatible = "qcom,ess-switch-ipq50xx";
|
||||
device_id = <0>;
|
||||
switch_mac_mode = <0xf>; /* mac mode for uniphy instance*/
|
||||
cmnblk_clk = "internal_96MHz"; /* cmnblk clk*/
|
||||
qcom,port_phyinfo {
|
||||
port@0 {
|
||||
port_id = <1>;
|
||||
phy_address = <7>;
|
||||
};
|
||||
port@1 {
|
||||
port_id = <2>;
|
||||
forced-speed = <1000>;
|
||||
forced-duplex = <1>;
|
||||
};
|
||||
};
|
||||
led_source@0 {
|
||||
source = <0>;
|
||||
mode = "normal";
|
||||
speed = "all";
|
||||
blink_en = "enable";
|
||||
active = "high";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wifi0: wifi@c000000 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
dp1 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <2>;
|
||||
reg = <0x39D00000 0x10000>;
|
||||
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
dp2 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,nss-dp";
|
||||
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
|
||||
clock-names = "nss-snoc-gmac-axi-clk";
|
||||
qcom,id = <1>;
|
||||
reg = <0x39C00000 0x10000>;
|
||||
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
|
||||
qcom,mactype = <2>;
|
||||
qcom,link-poll = <1>;
|
||||
qcom,phy-mdio-addr = <7>;
|
||||
mdio-bus = <&mdio0>;
|
||||
local-mac-address = [000000000000];
|
||||
phy-mode = "sgmii";
|
||||
};
|
||||
|
||||
|
||||
qcom,test@0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
lpass: lpass@0xA000000{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm: pcm@0xA3C0000{
|
||||
pinctrl-0 = <&audio_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&button_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
button@1 {
|
||||
label = "rst";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <1>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
pcm_lb: pcm_lb@0 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
status = "ok";
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
pinctrl-0 = <&phy_led_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
blsp1_uart_pins: blsp1_uart_pins {
|
||||
blsp1_uart_rx_tx {
|
||||
pins = "gpio31", "gpio33";
|
||||
function = "blsp1_uart1";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
blsp0_spi_pins: blsp0_spi_pins {
|
||||
mux {
|
||||
pins = "gpio10", "gpio11", "gpio12", "gpio13";
|
||||
function = "blsp0_spi";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
qspi_nand_pins: qspi_nand_pins {
|
||||
qspi_clock {
|
||||
pins = "gpio9";
|
||||
function = "qspi_clk";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_cs {
|
||||
pins = "gpio8";
|
||||
function = "qspi_cs";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_0 {
|
||||
pins = "gpio7";
|
||||
function = "qspi0";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_1 {
|
||||
pins = "gpio6";
|
||||
function = "qspi1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_2 {
|
||||
pins = "gpio5";
|
||||
function = "qspi2";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
qspi_data_3 {
|
||||
pins = "gpio4";
|
||||
function = "qspi3";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1_pins: mdio_pinmux {
|
||||
mux_0 {
|
||||
pins = "gpio36";
|
||||
function = "mdc";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
mux_1 {
|
||||
pins = "gpio37";
|
||||
function = "mdio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
phy_led_pins: phy_led_pins {
|
||||
gephy_led_pin {
|
||||
pins = "gpio46";
|
||||
function = "led0";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
i2c_pins: i2c_pins {
|
||||
i2c_scl {
|
||||
pins = "gpio25";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
i2c_sda {
|
||||
pins = "gpio26";
|
||||
function = "blsp2_i2c1";
|
||||
drive-strength = <8>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
button_pins: button_pins {
|
||||
wps_button {
|
||||
pins = "gpio38";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
rst_button {
|
||||
pins = "gpio27";
|
||||
function = "gpio";
|
||||
drive-strength = <8>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
};
|
||||
audio_pins: audio_pinmux {
|
||||
mux_1 {
|
||||
pins = "gpio24";
|
||||
function = "audio_rxbclk";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_2 {
|
||||
pins = "gpio25";
|
||||
function = "audio_rxfsync";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
mux_5 {
|
||||
pins = "gpio28";
|
||||
function = "audio_txbclk";
|
||||
drive-strength = <8>;
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pwm_pins: pwm_pinmux {
|
||||
mux_1 {
|
||||
pins = "gpio0";
|
||||
function = "pwm10";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
mux_2 {
|
||||
pins = "gpio1";
|
||||
function = "pwm20";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
mux_3 {
|
||||
pins = "gpio45";
|
||||
function = "pwm3";
|
||||
drive-strength = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&soc {
|
||||
|
||||
pwm: pwm@0x1941010 {
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
pinctrl-names = "default";
|
||||
used-pwm-indices = <1>, <1>, <1>, <1>;
|
||||
dft-pwm-status = <1>, <0>, <0>, <0>;
|
||||
status = "ok";
|
||||
};
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
status = "disabled";
|
||||
device-power-gpio = <&tlmm 24 1>;
|
||||
};
|
||||
|
||||
&eud {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1 {
|
||||
status = "ok";
|
||||
perst-gpio = <&tlmm 18 1>;
|
||||
};
|
||||
|
||||
&pcie_x2 {
|
||||
status = "disabled";
|
||||
perst-gpio = <&tlmm 15 1>;
|
||||
};
|
||||
|
||||
&dwc_0 {
|
||||
/delete-property/ #phy-cells;
|
||||
/delete-property/ phys;
|
||||
/delete-property/ phy-names;
|
||||
};
|
||||
|
||||
&hs_m31phy_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&pcie_x1phy {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pcie_x2phy {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pcie_x1_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_0: qcom,mhi@0 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie_x2_rp {
|
||||
status = "disabled";
|
||||
|
||||
mhi_1: qcom,mhi@1 {
|
||||
reg = <0 0 0 0 0 >;
|
||||
qrtr_instance_id = <0x21>;
|
||||
#address-cells = <0x2>;
|
||||
#size-cells = <0x2>;
|
||||
memory-region = <&mhi_region1>;
|
||||
#if !defined(__CNSS2__)
|
||||
base-addr = <0x4E900000>;
|
||||
m3-dump-addr = <0x4FD00000>;
|
||||
etr-addr = <0x4FE00000>;
|
||||
qcom,caldb-addr = <0x4FF00000>;
|
||||
qcom,tgt-mem-mode = <0x1>;
|
||||
mhi,max-channels = <30>;
|
||||
mhi,timeout = <10000>;
|
||||
qcom,board_id = <0xa4>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&wifi3 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qfprom {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&tsens {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&qcom_q6v5_wcss {
|
||||
qcom,multipd_arch;
|
||||
memory-region = <&q6_mem_regions>;
|
||||
qcom,share_bootargs;
|
||||
qcom,bootargs_smem = <507>;
|
||||
boot-args = <0x2 0x4 0x2 0x12 0x0 0x0>;
|
||||
|
||||
/* IPQ5018 */
|
||||
q6v5_wcss_userpd1 {
|
||||
m3_firmware = "IPQ5018/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 8 0>,
|
||||
<&wcss_smp2p_in 9 0>,
|
||||
<&wcss_smp2p_in 12 0>,
|
||||
<&wcss_smp2p_in 11 0>;
|
||||
interrupt-names ="fatal",
|
||||
"ready",
|
||||
"spawn_ack",
|
||||
"stop-ack";
|
||||
qcom,smem-states = <&wcss_smp2p_out 8>,
|
||||
<&wcss_smp2p_out 9>,
|
||||
<&wcss_smp2p_out 10>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
qca,asid = <1>;
|
||||
qca,auto-restart;
|
||||
qca,int_radio;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>;
|
||||
#else
|
||||
memory-region = <&q6_ipq5018_data>, <&m3_dump>,
|
||||
<&q6_etr_region>, <&q6_caldb_region>;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* QCN6122 5G */
|
||||
q6v5_wcss_userpd2 {
|
||||
m3_firmware = "qcn6122/m3_fw.mdt";
|
||||
interrupts-extended = <&wcss_smp2p_in 16 0>,
|
||||
<&wcss_smp2p_in 17 0>,
|
||||
<&wcss_smp2p_in 20 0>,
|
||||
<&wcss_smp2p_in 19 0>;
|
||||
interrupt-names ="fatal",
|
||||
"ready",
|
||||
"spawn_ack",
|
||||
"stop-ack";
|
||||
qcom,smem-states = <&wcss_smp2p_out 16>,
|
||||
<&wcss_smp2p_out 17>,
|
||||
<&wcss_smp2p_out 18>;
|
||||
qcom,smem-state-names = "shutdown",
|
||||
"stop",
|
||||
"spawn";
|
||||
qca,asid = <2>;
|
||||
qca,auto-restart;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>;
|
||||
#else
|
||||
memory-region = <&q6_qcn6122_data1>, <&m3_dump_qcn6122_1>,
|
||||
<&q6_qcn6122_etr_1>, <&q6_qcn6122_caldb_1>;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_0 {
|
||||
pinctrl-0 = <&i2c_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&qgic_msi_0 {
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
/* IPQ5018 */
|
||||
qcom,multipd_arch;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x24>;
|
||||
qcom,bdf-addr = <0x0 0x4C000000 0x4C000000 0x0 0x0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,caldb-addr = <0x0 0x4D000000 0 0 0>;
|
||||
#else
|
||||
qcom,caldb-addr = <0x4D000000>;
|
||||
m3-dump-addr = <0x4CE00000>;
|
||||
#endif
|
||||
qcom,caldb-size = <0x200000>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd1";
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
/* QCN6122 5G */
|
||||
qcom,multipd_arch;
|
||||
#ifdef __IPQ_MEM_PROFILE_256_MB__
|
||||
qcom,tgt-mem-mode = <2>;
|
||||
#else
|
||||
qcom,tgt-mem-mode = <1>;
|
||||
#endif
|
||||
qcom,board_id = <0x60>;
|
||||
qcom,bdf-addr = <0x0 0x4D200000 0x4CF00000 0x0 0x0>;
|
||||
#ifdef __CNSS2__
|
||||
qcom,caldb-addr = <0x0 0x4E400000 0 0 0>;
|
||||
#else
|
||||
qcom,caldb-addr = <0x4E400000>;
|
||||
m3-dump-addr = <0x4E200000>;
|
||||
#endif
|
||||
qcom,caldb-size = <0x500000>;
|
||||
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
|
||||
status = "ok";
|
||||
};
|
||||
@@ -28,6 +28,15 @@ define Device/cig_wf186w
|
||||
endef
|
||||
TARGET_DEVICES += cig_wf186w
|
||||
|
||||
define Device/cig_wf186h
|
||||
DEVICE_TITLE := Cigtech WF-186h
|
||||
DEVICE_DTS := qcom-ipq5018-cig-wf186h
|
||||
SUPPORTED_DEVICES := cig,wf186h
|
||||
DEVICE_PACKAGES := ath11k-wifi-cig-wf186h ath11k-firmware-ipq50xx-map-spruce
|
||||
DEVICE_DTS_CONFIG := config@mp03.3
|
||||
endef
|
||||
TARGET_DEVICES += cig_wf186h
|
||||
|
||||
define Device/cybertan_eww622_a1
|
||||
DEVICE_TITLE := CyberTan EWW622-A1
|
||||
DEVICE_DTS := qcom-ipq5018-eww622-a1
|
||||
|
||||
@@ -82,7 +82,7 @@ CONFIG_MIGRATION=y
|
||||
CONFIG_MPILIB=y
|
||||
CONFIG_MSM_SECURE_BUFFER=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_SWITCHDEV=y
|
||||
# CONFIG_NET_SWITCHDEV is not set
|
||||
CONFIG_NUM_ALT_PARTITION=16
|
||||
CONFIG_OF_IOMMU=y
|
||||
CONFIG_OID_REGISTRY=y
|
||||
|
||||
@@ -4,7 +4,7 @@ CONFIG_ARCH_IPQ807x=y
|
||||
CONFIG_IPQ_ADSS_807x=y
|
||||
CONFIG_IPQ_APSS_807x=y
|
||||
CONFIG_IPQ_GCC_807x=y
|
||||
CONFIG_NET_SWITCHDEV=y
|
||||
# CONFIG_NET_SWITCHDEV is not set
|
||||
CONFIG_NUM_ALT_PARTITION=16
|
||||
CONFIG_PINCTRL_IPQ807x=y
|
||||
# CONFIG_IPC_LOGGING is not set
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
From: Andy Ren <andy.ren@getcruise.com>
|
||||
Date: Mon, 7 Nov 2022 09:42:42 -0800
|
||||
Subject: [PATCH] net/core: Allow live renaming when an interface is up
|
||||
|
||||
Allow a network interface to be renamed when the interface
|
||||
is up.
|
||||
|
||||
As described in the netconsole documentation [1], when netconsole is
|
||||
used as a built-in, it will bring up the specified interface as soon as
|
||||
possible. As a result, user space will not be able to rename the
|
||||
interface since the kernel disallows renaming of interfaces that are
|
||||
administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set
|
||||
by the kernel.
|
||||
|
||||
The original solution [2] to this problem was to add a new parameter to
|
||||
the netconsole configuration parameters that allows renaming of
|
||||
the interface used by netconsole while it is administratively up.
|
||||
However, during the discussion that followed, it became apparent that we
|
||||
have no reason to keep the current restriction and instead we should
|
||||
allow user space to rename interfaces regardless of their administrative
|
||||
state:
|
||||
|
||||
1. The restriction was put in place over 20 years ago when renaming was
|
||||
only possible via IOCTL and before rtnetlink started notifying user
|
||||
space about such changes like it does today.
|
||||
|
||||
2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version
|
||||
5.2 and no regressions were reported.
|
||||
|
||||
3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about
|
||||
the administrative state of interface.
|
||||
|
||||
Therefore, allow user space to rename running interfaces by removing the
|
||||
restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in
|
||||
possible triage by emitting a message to the kernel log that an
|
||||
interface was renamed while UP.
|
||||
|
||||
[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst
|
||||
[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/
|
||||
|
||||
Signed-off-by: Andy Ren <andy.ren@getcruise.com>
|
||||
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||||
Reviewed-by: David Ahern <dsahern@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -1152,8 +1152,6 @@ int dev_change_name(struct net_device *d
|
||||
BUG_ON(!dev_net(dev));
|
||||
|
||||
net = dev_net(dev);
|
||||
- if (dev->flags & IFF_UP)
|
||||
- return -EBUSY;
|
||||
|
||||
write_seqcount_begin(&devnet_rename_seq);
|
||||
|
||||
@@ -1171,7 +1169,8 @@ int dev_change_name(struct net_device *d
|
||||
}
|
||||
|
||||
if (oldname[0] && !strchr(oldname, '%'))
|
||||
- netdev_info(dev, "renamed from %s\n", oldname);
|
||||
+ netdev_info(dev, "renamed from %s%s\n", oldname,
|
||||
+ dev->flags & IFF_UP ? " (while UP)" : "");
|
||||
|
||||
old_assign_type = dev->name_assign_type;
|
||||
dev->name_assign_type = NET_NAME_RENAMED;
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as nl80211 from "nl80211";
|
||||
import * as rtnl from "rtnl";
|
||||
import { readfile } from "fs";
|
||||
import { readfile, glob, basename, readlink } from "fs";
|
||||
|
||||
const iftypes = {
|
||||
ap: nl80211.const.NL80211_IFTYPE_AP,
|
||||
@@ -94,6 +94,156 @@ function wdev_create(phy, name, data)
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -150,7 +300,7 @@ function is_equal(val1, val2) {
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (!val1[key])
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
@@ -165,4 +315,4 @@ function vlist_new(cb) {
|
||||
}, vlist_proto);
|
||||
}
|
||||
|
||||
export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };
|
||||
export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
|
||||
@@ -725,8 +725,7 @@ hostapd_set_bss_options() {
|
||||
[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
|
||||
}
|
||||
|
||||
set_default nasid "${macaddr//\:}"
|
||||
append bss_conf "nas_identifier=$nasid" "$N"
|
||||
[ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
|
||||
|
||||
[ -n "$acct_server" ] && {
|
||||
append bss_conf "acct_server_addr=$acct_server" "$N"
|
||||
@@ -772,9 +771,9 @@ hostapd_set_bss_options() {
|
||||
# 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
|
||||
vlan_possible=1
|
||||
[ "$macfilter" = radius ] && {
|
||||
append_radius_server
|
||||
vlan_possible=1
|
||||
}
|
||||
;;
|
||||
psk|sae|psk-sae)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
let libubus = require("ubus");
|
||||
import { open, readfile } from "fs";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac } from "common";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common";
|
||||
|
||||
let ubus = libubus.connect();
|
||||
|
||||
@@ -31,7 +31,7 @@ function iface_remove(cfg)
|
||||
wdev_remove(bss.ifname);
|
||||
}
|
||||
|
||||
function iface_gen_config(phy, config)
|
||||
function iface_gen_config(phy, config, start_disabled)
|
||||
{
|
||||
let str = `data:
|
||||
${join("\n", config.radio.data)}
|
||||
@@ -41,18 +41,92 @@ channel=${config.radio.channel}
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
let type = i > 0 ? "bss" : "interface";
|
||||
let nasid = bss.nasid ?? replace(bss.bssid, ":", "");
|
||||
|
||||
str += `
|
||||
${type}=${bss.ifname}
|
||||
bssid=${bss.bssid}
|
||||
${join("\n", bss.data)}
|
||||
nas_identifier=${nasid}
|
||||
`;
|
||||
if (start_disabled)
|
||||
str += `
|
||||
start_disabled=1
|
||||
`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function iface_restart(phy, config, old_config)
|
||||
function iface_freq_info(iface, config, params)
|
||||
{
|
||||
let freq = params.frequency;
|
||||
if (!freq)
|
||||
return null;
|
||||
|
||||
let sec_offset = params.sec_chan_offset;
|
||||
if (sec_offset != -1 && sec_offset != 1)
|
||||
sec_offset = 0;
|
||||
|
||||
let width = 0;
|
||||
for (let line in config.radio.data) {
|
||||
if (!sec_offset && match(line, /^ht_capab=.*HT40/)) {
|
||||
sec_offset = null; // auto-detect
|
||||
continue;
|
||||
}
|
||||
|
||||
let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
val = int(val[2]);
|
||||
if (val > width)
|
||||
width = val;
|
||||
}
|
||||
|
||||
if (freq < 4000)
|
||||
width = 0;
|
||||
|
||||
return hostapd.freq_info(freq, sec_offset, width);
|
||||
}
|
||||
|
||||
function iface_add(phy, config, phy_status)
|
||||
{
|
||||
let config_inline = iface_gen_config(phy, config, !!phy_status);
|
||||
|
||||
let bss = config.bss[0];
|
||||
let ret = hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
if (!phy_status)
|
||||
return true;
|
||||
|
||||
let iface = hostapd.interfaces[bss.ifname];
|
||||
if (!iface)
|
||||
return false;
|
||||
|
||||
let freq_info = iface_freq_info(iface, config, phy_status);
|
||||
|
||||
return iface.start(freq_info) >= 0;
|
||||
}
|
||||
|
||||
function iface_config_macaddr_list(config)
|
||||
{
|
||||
let macaddr_list = {};
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
if (!bss.default_macaddr)
|
||||
macaddr_list[bss.bssid] = i;
|
||||
}
|
||||
|
||||
return macaddr_list;
|
||||
}
|
||||
|
||||
function iface_restart(phydev, config, old_config)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
iface_remove(old_config);
|
||||
iface_remove(config);
|
||||
|
||||
@@ -61,15 +135,29 @@ function iface_restart(phy, config, old_config)
|
||||
return;
|
||||
}
|
||||
|
||||
phydev.macaddr_init(iface_config_macaddr_list(config));
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
if (bss.default_macaddr)
|
||||
bss.bssid = phydev.macaddr_next();
|
||||
}
|
||||
|
||||
let bss = config.bss[0];
|
||||
let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
||||
if (err)
|
||||
hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
||||
let config_inline = iface_gen_config(phy, config);
|
||||
|
||||
let ubus = hostapd.data.ubus;
|
||||
let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy });
|
||||
if (phy_status && phy_status.state == "COMPLETED") {
|
||||
if (iface_add(phy, config, phy_status))
|
||||
return;
|
||||
|
||||
hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`);
|
||||
}
|
||||
|
||||
ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
|
||||
if (hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`) < 0)
|
||||
if (!iface_add(phy, config))
|
||||
hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
||||
ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
|
||||
}
|
||||
@@ -111,8 +199,65 @@ function bss_reload_psk(bss, config, old_config)
|
||||
hostapd.printf(`Reload WPA PSK file for bss ${config.ifname}: ${ret}`);
|
||||
}
|
||||
|
||||
function iface_reload_config(phy, config, old_config)
|
||||
function remove_file_fields(config)
|
||||
{
|
||||
return filter(config, (line) => !hostapd.data.file_fields[split(line, "=")[0]]);
|
||||
}
|
||||
|
||||
function bss_remove_file_fields(config)
|
||||
{
|
||||
let new_cfg = {};
|
||||
|
||||
for (let key in config)
|
||||
new_cfg[key] = config[key];
|
||||
new_cfg.data = remove_file_fields(new_cfg.data);
|
||||
new_cfg.hash = {};
|
||||
for (let key in config.hash)
|
||||
new_cfg.hash[key] = config.hash[key];
|
||||
delete new_cfg.hash.wpa_psk_file;
|
||||
delete new_cfg.hash.vlan_file;
|
||||
|
||||
return new_cfg;
|
||||
}
|
||||
|
||||
function bss_config_hash(config)
|
||||
{
|
||||
return hostapd.sha1(remove_file_fields(config) + "");
|
||||
}
|
||||
|
||||
function bss_find_existing(config, prev_config, prev_hash)
|
||||
{
|
||||
let hash = bss_config_hash(config.data);
|
||||
|
||||
for (let i = 0; i < length(prev_config.bss); i++) {
|
||||
if (!prev_hash[i] || hash != prev_hash[i])
|
||||
continue;
|
||||
|
||||
prev_hash[i] = null;
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function get_config_bss(config, idx)
|
||||
{
|
||||
if (!config.bss[idx]) {
|
||||
hostapd.printf(`Invalid bss index ${idx}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
let ifname = config.bss[idx].ifname;
|
||||
if (!ifname)
|
||||
hostapd.printf(`Could not find bss ${config.bss[idx].ifname}`);
|
||||
|
||||
return hostapd.bss[ifname];
|
||||
}
|
||||
|
||||
function iface_reload_config(phydev, config, old_config)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
if (!old_config || !is_equal(old_config.radio, config.radio))
|
||||
return false;
|
||||
|
||||
@@ -122,82 +267,230 @@ function iface_reload_config(phy, config, old_config)
|
||||
if (!old_config.bss || !old_config.bss[0])
|
||||
return false;
|
||||
|
||||
if (config.bss[0].ifname != old_config.bss[0].ifname)
|
||||
return false;
|
||||
|
||||
let iface_name = config.bss[0].ifname;
|
||||
let iface_name = old_config.bss[0].ifname;
|
||||
let iface = hostapd.interfaces[iface_name];
|
||||
if (!iface)
|
||||
if (!iface) {
|
||||
hostapd.printf(`Could not find previous interface ${iface_name}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let first_bss = hostapd.bss[iface_name];
|
||||
if (!first_bss)
|
||||
if (!first_bss) {
|
||||
hostapd.printf(`Could not find bss of previous interface ${iface_name}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let macaddr_list = iface_config_macaddr_list(config);
|
||||
let bss_list = [];
|
||||
let bss_list_cfg = [];
|
||||
let prev_bss_hash = [];
|
||||
|
||||
for (let bss in old_config.bss) {
|
||||
let hash = bss_config_hash(bss.data);
|
||||
push(prev_bss_hash, bss_config_hash(bss.data));
|
||||
}
|
||||
|
||||
// Step 1: find (possibly renamed) interfaces with the same config
|
||||
// and store them in the new order (with gaps)
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let prev;
|
||||
|
||||
// For fullmac devices, the first interface needs to be preserved,
|
||||
// since it's treated as the master
|
||||
if (!i && phy_is_fullmac(phy)) {
|
||||
prev = 0;
|
||||
prev_bss_hash[0] = null;
|
||||
} else {
|
||||
prev = bss_find_existing(config.bss[i], old_config, prev_bss_hash);
|
||||
}
|
||||
if (prev < 0)
|
||||
continue;
|
||||
|
||||
let cur_config = config.bss[i];
|
||||
let prev_config = old_config.bss[prev];
|
||||
|
||||
let prev_bss = get_config_bss(old_config, prev);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
// try to preserve MAC address of this BSS by reassigning another
|
||||
// BSS if necessary
|
||||
if (cur_config.default_macaddr &&
|
||||
!macaddr_list[prev_config.bssid]) {
|
||||
macaddr_list[prev_config.bssid] = i;
|
||||
cur_config.bssid = prev_config.bssid;
|
||||
}
|
||||
|
||||
bss_list[i] = prev_bss;
|
||||
bss_list_cfg[i] = old_config.bss[prev];
|
||||
}
|
||||
|
||||
if (config.mbssid && !bss_list_cfg[0]) {
|
||||
hostapd.printf("First BSS changed with MBSSID enabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: if none were found, rename and preserve the first one
|
||||
if (length(bss_list) == 0) {
|
||||
// can't change the bssid of the first bss
|
||||
if (config.bss[0].bssid != old_config.bss[0].bssid) {
|
||||
if (!config.bss[0].default_macaddr) {
|
||||
hostapd.printf(`BSSID of first interface changed: ${lc(old_config.bss[0].bssid)} -> ${lc(config.bss[0].bssid)}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
config.bss[0].bssid = old_config.bss[0].bssid;
|
||||
}
|
||||
|
||||
let prev_bss = get_config_bss(old_config, 0);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
macaddr_list[config.bss[0].bssid] = 0;
|
||||
bss_list[0] = prev_bss;
|
||||
bss_list_cfg[0] = old_config.bss[0];
|
||||
prev_bss_hash[0] = null;
|
||||
}
|
||||
|
||||
// Step 3: delete all unused old interfaces
|
||||
for (let i = 0; i < length(prev_bss_hash); i++) {
|
||||
if (!prev_bss_hash[i])
|
||||
continue;
|
||||
|
||||
let prev_bss = get_config_bss(old_config, i);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
let ifname = old_config.bss[i].ifname;
|
||||
hostapd.printf(`Remove bss '${ifname}' on phy '${phy}'`);
|
||||
prev_bss.delete();
|
||||
wdev_remove(ifname);
|
||||
}
|
||||
|
||||
// Step 4: rename preserved interfaces, use temporary name on duplicates
|
||||
let rename_list = [];
|
||||
for (let i = 0; i < length(bss_list); i++) {
|
||||
if (!bss_list[i])
|
||||
continue;
|
||||
|
||||
let old_ifname = bss_list_cfg[i].ifname;
|
||||
let new_ifname = config.bss[i].ifname;
|
||||
if (old_ifname == new_ifname)
|
||||
continue;
|
||||
|
||||
if (hostapd.bss[new_ifname]) {
|
||||
new_ifname = "tmp_" + substr(hostapd.sha1(new_ifname), 0, 8);
|
||||
push(rename_list, i);
|
||||
}
|
||||
|
||||
hostapd.printf(`Rename bss ${old_ifname} to ${new_ifname}`);
|
||||
if (!bss_list[i].rename(new_ifname)) {
|
||||
hostapd.printf(`Failed to rename bss ${old_ifname} to ${new_ifname}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
bss_list_cfg[i].ifname = new_ifname;
|
||||
}
|
||||
|
||||
// Step 5: rename interfaces with temporary names
|
||||
for (let i in rename_list) {
|
||||
let new_ifname = config.bss[i].ifname;
|
||||
if (!bss_list[i].rename(new_ifname)) {
|
||||
hostapd.printf(`Failed to rename bss to ${new_ifname}`);
|
||||
return false;
|
||||
}
|
||||
bss_list_cfg[i].ifname = new_ifname;
|
||||
}
|
||||
|
||||
// Step 6: assign BSSID for newly created interfaces
|
||||
let macaddr_data = {
|
||||
num_global: config.num_global_macaddr ?? 1,
|
||||
mbssid: config.mbssid ?? 0,
|
||||
};
|
||||
macaddr_list = phydev.macaddr_init(macaddr_list, macaddr_data);
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
if (bss_list[i])
|
||||
continue;
|
||||
let bsscfg = config.bss[i];
|
||||
|
||||
let mac_idx = macaddr_list[bsscfg.bssid];
|
||||
if (mac_idx < 0)
|
||||
macaddr_list[bsscfg.bssid] = i;
|
||||
if (mac_idx == i)
|
||||
continue;
|
||||
|
||||
// statically assigned bssid of the new interface is in conflict
|
||||
// with the bssid of a reused interface. reassign the reused interface
|
||||
if (!bsscfg.default_macaddr) {
|
||||
// can't update bssid of the first BSS, need to restart
|
||||
if (!mac_idx < 0)
|
||||
return false;
|
||||
|
||||
bsscfg = config.bss[mac_idx];
|
||||
}
|
||||
|
||||
let addr = phydev.macaddr_next(i);
|
||||
if (!addr) {
|
||||
hostapd.printf(`Failed to generate mac address for phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
bsscfg.bssid = addr;
|
||||
}
|
||||
|
||||
let config_inline = iface_gen_config(phy, config);
|
||||
|
||||
bss_reload_psk(first_bss, config.bss[0], old_config.bss[0]);
|
||||
if (!is_equal(config.bss[0], old_config.bss[0])) {
|
||||
if (phy_is_fullmac(phy))
|
||||
return false;
|
||||
// Step 7: fill in the gaps with new interfaces
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let ifname = config.bss[i].ifname;
|
||||
let bss = bss_list[i];
|
||||
|
||||
if (config.bss[0].bssid != old_config.bss[0].bssid)
|
||||
if (bss)
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Add bss ${ifname} on phy ${phy}`);
|
||||
bss_list[i] = iface.add_bss(config_inline, i);
|
||||
if (!bss_list[i]) {
|
||||
hostapd.printf(`Failed to add new bss ${ifname} on phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: update interface bss order
|
||||
if (!iface.set_bss_order(bss_list)) {
|
||||
hostapd.printf(`Failed to update BSS order on phy '${phy}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 9: update config
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
if (!bss_list_cfg[i])
|
||||
continue;
|
||||
|
||||
let ifname = config.bss[i].ifname;
|
||||
let bss = bss_list[i];
|
||||
|
||||
if (is_equal(config.bss[i], bss_list_cfg[i]))
|
||||
continue;
|
||||
|
||||
if (is_equal(bss_remove_file_fields(config.bss[i]),
|
||||
bss_remove_file_fields(bss_list_cfg[i]))) {
|
||||
hostapd.printf(`Update config data files for bss ${ifname}`);
|
||||
if (bss.set_config(config_inline, i, true) < 0) {
|
||||
hostapd.printf(`Could not update config data files for bss ${ifname}`);
|
||||
return false;
|
||||
} else {
|
||||
bss.ctrl("RELOAD_WPA_PSK");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bss_reload_psk(bss, config.bss[i], bss_list_cfg[i]);
|
||||
if (is_equal(config.bss[i], bss_list_cfg[i]))
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
|
||||
if (first_bss.set_config(config_inline, 0) < 0) {
|
||||
hostapd.printf(`Failed to set config`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let new_cfg = array_to_obj(config.bss, "ifname", 1);
|
||||
let old_cfg = array_to_obj(old_config.bss, "ifname", 1);
|
||||
|
||||
for (let name in old_cfg) {
|
||||
let bss = hostapd.bss[name];
|
||||
if (!bss) {
|
||||
hostapd.printf(`bss '${name}' not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new_cfg[name]) {
|
||||
hostapd.printf(`Remove bss '${name}' on phy '${phy}'`);
|
||||
bss.delete();
|
||||
wdev_remove(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
let new_cfg_data = new_cfg[name];
|
||||
delete new_cfg[name];
|
||||
|
||||
if (is_equal(old_cfg[name], new_cfg_data))
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Reload config for bss '${name}' on phy '${phy}'`);
|
||||
let idx = find_array_idx(config.bss, "ifname", name);
|
||||
if (idx < 0) {
|
||||
hostapd.printf(`bss index not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss.set_config(config_inline, idx) < 0) {
|
||||
hostapd.printf(`Failed to set config`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let name in new_cfg) {
|
||||
hostapd.printf(`Add bss '${name}' on phy '${phy}'`);
|
||||
|
||||
let idx = find_array_idx(config.bss, "ifname", name);
|
||||
if (idx < 0) {
|
||||
hostapd.printf(`bss index not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iface.add_bss(config_inline, idx) < 0) {
|
||||
hostapd.printf(`Failed to add bss`);
|
||||
if (bss.set_config(config_inline, i) < 0) {
|
||||
hostapd.printf(`Failed to set config for bss ${ifname}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,6 +498,14 @@ function iface_reload_config(phy, config, old_config)
|
||||
return true;
|
||||
}
|
||||
|
||||
function iface_update_supplicant_macaddr(phy, config)
|
||||
{
|
||||
let macaddr_list = [];
|
||||
for (let i = 0; i < length(config.bss); i++)
|
||||
push(macaddr_list, config.bss[i].bssid);
|
||||
ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
|
||||
}
|
||||
|
||||
function iface_set_config(phy, config)
|
||||
{
|
||||
let old_config = hostapd.data.config[phy];
|
||||
@@ -214,14 +515,28 @@ function iface_set_config(phy, config)
|
||||
if (!config)
|
||||
return iface_remove(old_config);
|
||||
|
||||
let ret = iface_reload_config(phy, config, old_config);
|
||||
if (ret) {
|
||||
hostapd.printf(`Reloaded settings for phy ${phy}`);
|
||||
return 0;
|
||||
let phydev = phy_open(phy);
|
||||
if (!phydev) {
|
||||
hostapd.printf(`Failed to open phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
let ret = iface_reload_config(phydev, config, old_config);
|
||||
if (ret) {
|
||||
iface_update_supplicant_macaddr(phy, config);
|
||||
hostapd.printf(`Reloaded settings for phy ${phy}`);
|
||||
return 0;
|
||||
}
|
||||
} catch (e) {
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
|
||||
hostapd.printf(`Restart interface for phy ${phy}`);
|
||||
return iface_restart(phy, config, old_config);
|
||||
let ret = iface_restart(phydev, config, old_config);
|
||||
iface_update_supplicant_macaddr(phy, config);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function config_add_bss(config, name)
|
||||
@@ -268,16 +583,28 @@ function iface_load_config(filename)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val[0] == "#num_global_macaddr" ||
|
||||
val[0] == "mbssid")
|
||||
config[val[0]] = int(val[1]);
|
||||
|
||||
push(config.radio.data, line);
|
||||
}
|
||||
|
||||
while ((line = trim(f.read("line"))) != null) {
|
||||
if (line == "#default_macaddr")
|
||||
bss.default_macaddr = true;
|
||||
|
||||
let val = split(line, "=", 2);
|
||||
if (!val[0])
|
||||
continue;
|
||||
|
||||
if (val[0] == "bssid")
|
||||
bss.bssid = val[1];
|
||||
if (val[0] == "bssid") {
|
||||
bss.bssid = lc(val[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val[0] == "nas_identifier")
|
||||
bss.nasid = val[1];
|
||||
|
||||
if (val[0] == "bss") {
|
||||
bss = config_add_bss(config, val[1]);
|
||||
@@ -294,28 +621,33 @@ function iface_load_config(filename)
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
function ex_wrap(func) {
|
||||
return (req) => {
|
||||
try {
|
||||
let ret = func(req);
|
||||
return ret;
|
||||
} catch(e) {
|
||||
hostapd.printf(`Exception in ubus function: ${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
};
|
||||
}
|
||||
|
||||
let main_obj = {
|
||||
reload: {
|
||||
args: {
|
||||
phy: "",
|
||||
},
|
||||
call: function(req) {
|
||||
try {
|
||||
let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
||||
for (let phy_name in phy_list) {
|
||||
let phy = hostapd.data.config[phy_name];
|
||||
let config = iface_load_config(phy.orig_file);
|
||||
iface_set_config(phy_name, config);
|
||||
}
|
||||
} catch(e) {
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
call: ex_wrap(function(req) {
|
||||
let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
||||
for (let phy_name in phy_list) {
|
||||
let phy = hostapd.data.config[phy_name];
|
||||
let config = iface_load_config(phy.orig_file);
|
||||
iface_set_config(phy_name, config);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
apsta_state: {
|
||||
args: {
|
||||
@@ -326,7 +658,7 @@ let main_obj = {
|
||||
csa: true,
|
||||
csa_count: 0,
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (req.args.up == null || !req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@@ -344,34 +676,10 @@ let main_obj = {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let freq = req.args.frequency;
|
||||
if (!freq)
|
||||
if (!req.args.frequency)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let sec_offset = req.args.sec_chan_offset;
|
||||
if (sec_offset != -1 && sec_offset != 1)
|
||||
sec_offset = 0;
|
||||
|
||||
let width = 0;
|
||||
for (let line in config.radio.data) {
|
||||
if (!sec_offset && match(line, /^ht_capab=.*HT40/)) {
|
||||
sec_offset = null; // auto-detect
|
||||
continue;
|
||||
}
|
||||
|
||||
let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
val = int(val[2]);
|
||||
if (val > width)
|
||||
width = val;
|
||||
}
|
||||
|
||||
if (freq < 4000)
|
||||
width = 0;
|
||||
|
||||
let freq_info = hostapd.freq_info(freq, sec_offset, width);
|
||||
let freq_info = iface_freq_info(iface, config, req.args);
|
||||
if (!freq_info)
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
|
||||
@@ -380,14 +688,34 @@ let main_obj = {
|
||||
freq_info.csa_count = req.args.csa_count ?? 10;
|
||||
ret = iface.switch_channel(freq_info);
|
||||
} else {
|
||||
iface.stop();
|
||||
ret = iface.start(freq_info);
|
||||
}
|
||||
if (!ret)
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
config_get_macaddr_list: {
|
||||
args: {
|
||||
phy: ""
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let ret = {
|
||||
macaddr: [],
|
||||
};
|
||||
|
||||
let config = hostapd.data.config[phy];
|
||||
if (!config)
|
||||
return ret;
|
||||
|
||||
ret.macaddr = map(config.bss, (bss) => bss.bssid);
|
||||
return ret;
|
||||
})
|
||||
},
|
||||
config_set: {
|
||||
args: {
|
||||
@@ -395,7 +723,7 @@ let main_obj = {
|
||||
config: "",
|
||||
prev_config: "",
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
let file = req.args.config;
|
||||
let prev_file = req.args.prev_config;
|
||||
@@ -403,34 +731,29 @@ let main_obj = {
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
try {
|
||||
if (prev_file && !hostapd.data.config[phy]) {
|
||||
let config = iface_load_config(prev_file);
|
||||
if (config)
|
||||
config.radio.data = [];
|
||||
hostapd.data.config[phy] = config;
|
||||
}
|
||||
|
||||
let config = iface_load_config(file);
|
||||
|
||||
hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
||||
iface_set_config(phy, config);
|
||||
} catch(e) {
|
||||
hostapd.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
if (prev_file && !hostapd.data.config[phy]) {
|
||||
let config = iface_load_config(prev_file);
|
||||
if (config)
|
||||
config.radio.data = [];
|
||||
hostapd.data.config[phy] = config;
|
||||
}
|
||||
|
||||
let config = iface_load_config(file);
|
||||
|
||||
hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
||||
iface_set_config(phy, config);
|
||||
|
||||
return {
|
||||
pid: hostapd.getpid()
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
config_add: {
|
||||
args: {
|
||||
iface: "",
|
||||
config: "",
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (!req.args.iface || !req.args.config)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@@ -440,19 +763,19 @@ let main_obj = {
|
||||
return {
|
||||
pid: hostapd.getpid()
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
config_remove: {
|
||||
args: {
|
||||
iface: ""
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (!req.args.iface)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
hostapd.remove_iface(req.args.iface);
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc";
|
||||
import { vlist_new, is_equal, wdev_create, wdev_remove, 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 new_config = shift(ARGV);
|
||||
let command = shift(ARGV);
|
||||
let phydev;
|
||||
|
||||
const mesh_params = [
|
||||
"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",
|
||||
@@ -33,6 +36,11 @@ function iface_start(wdev)
|
||||
system([ "ip", "link", "set", "dev", ifname, "down" ]);
|
||||
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);
|
||||
system([ "ip", "link", "set", "dev", ifname, "up" ]);
|
||||
if (wdev.freq)
|
||||
@@ -47,7 +55,7 @@ function iface_start(wdev)
|
||||
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 [ "beacon-interval", "mcast-rate" ])
|
||||
for (let key in [ "mcast-rate", "beacon-interval" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
@@ -114,43 +122,86 @@ function add_existing(phy, config)
|
||||
}
|
||||
}
|
||||
|
||||
function usage()
|
||||
{
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
|
||||
|
||||
let statefile = `/var/run/wdev-${phy}.json`;
|
||||
|
||||
for (let dev in ARGV)
|
||||
keep_devices[dev] = true;
|
||||
|
||||
if (!phy || !new_config) {
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <config> [<device]...]\n`);
|
||||
Commands:
|
||||
set_config <config> [<device]...] - set phy configuration
|
||||
get_macaddr <id> - get phy MAC address for vif index <id>
|
||||
`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!readfile(`/sys/class/ieee80211/${phy}/index`)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
add_ifname(new_config);
|
||||
config.update(new_config);
|
||||
|
||||
drop_inactive(config.data);
|
||||
delete_ifname(config.data);
|
||||
writefile(statefile, sprintf("%J", config.data));
|
||||
commands[command](ARGV);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
let libubus = require("ubus");
|
||||
import { open, readfile } from "fs";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new } from "common";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_open } from "common";
|
||||
|
||||
let ubus = libubus.connect();
|
||||
|
||||
wpas.data.config = {};
|
||||
wpas.data.iface_phy = {};
|
||||
wpas.data.macaddr_list = {};
|
||||
|
||||
function iface_stop(iface)
|
||||
{
|
||||
@@ -20,16 +21,23 @@ function iface_stop(iface)
|
||||
iface.running = false;
|
||||
}
|
||||
|
||||
function iface_start(phy, iface)
|
||||
function iface_start(phydev, iface, macaddr_list)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
if (iface.running)
|
||||
return;
|
||||
|
||||
let ifname = iface.config.iface;
|
||||
let wdev_config = {};
|
||||
for (let field in iface.config)
|
||||
wdev_config[field] = iface.config[field];
|
||||
if (!wdev_config.macaddr)
|
||||
wdev_config.macaddr = phydev.macaddr_next();
|
||||
|
||||
wpas.data.iface_phy[ifname] = phy;
|
||||
wdev_remove(ifname);
|
||||
let ret = wdev_create(phy, ifname, iface.config);
|
||||
let ret = wdev_create(phy, ifname, wdev_config);
|
||||
if (ret)
|
||||
wpas.printf(`Failed to create device ${ifname}: ${ret}`);
|
||||
wpas.add_iface(iface.config);
|
||||
@@ -43,6 +51,11 @@ function iface_cb(new_if, old_if)
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_if && old_if)
|
||||
wpas.printf(`Update configuration for interface ${old_if.config.iface}`);
|
||||
else if (old_if)
|
||||
wpas.printf(`Remove interface ${old_if.config.iface}`);
|
||||
|
||||
if (old_if)
|
||||
iface_stop(old_if);
|
||||
}
|
||||
@@ -73,9 +86,22 @@ function set_config(phy_name, config_list)
|
||||
function start_pending(phy_name)
|
||||
{
|
||||
let phy = wpas.data.config[phy_name];
|
||||
let ubus = wpas.data.ubus;
|
||||
|
||||
if (!phy || !phy.data)
|
||||
return;
|
||||
|
||||
let phydev = phy_open(phy_name);
|
||||
if (!phydev) {
|
||||
wpas.printf(`Could not open phy ${phy_name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let macaddr_list = wpas.data.macaddr_list[phy_name];
|
||||
phydev.macaddr_init(macaddr_list);
|
||||
|
||||
for (let ifname in phy.data)
|
||||
iface_start(phy_name, phy.data[ifname]);
|
||||
iface_start(phydev, phy.data[ifname]);
|
||||
}
|
||||
|
||||
let main_obj = {
|
||||
@@ -106,6 +132,55 @@ let main_obj = {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
phy_set_macaddr_list: {
|
||||
args: {
|
||||
phy: "",
|
||||
macaddr: [],
|
||||
},
|
||||
call: function(req) {
|
||||
let phy = req.args.phy;
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
wpas.data.macaddr_list[phy] = req.args.macaddr;
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
phy_status: {
|
||||
args: {
|
||||
phy: ""
|
||||
},
|
||||
call: function(req) {
|
||||
if (!req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let phy = wpas.data.config[req.args.phy];
|
||||
if (!phy)
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
|
||||
for (let ifname in phy.data) {
|
||||
try {
|
||||
let iface = wpas.interfaces[ifname];
|
||||
if (!iface)
|
||||
continue;
|
||||
|
||||
let status = iface.status();
|
||||
if (!status)
|
||||
continue;
|
||||
|
||||
if (status.state == "INTERFACE_DISABLED")
|
||||
continue;
|
||||
|
||||
status.ifname = ifname;
|
||||
return status;
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
}
|
||||
},
|
||||
config_set: {
|
||||
args: {
|
||||
phy: "",
|
||||
@@ -116,6 +191,7 @@ let main_obj = {
|
||||
if (!req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
wpas.printf(`Set new config for phy ${req.args.phy}`);
|
||||
try {
|
||||
if (req.args.config)
|
||||
set_config(req.args.phy, req.args.config);
|
||||
@@ -188,6 +264,7 @@ function iface_hostapd_notify(phy, ifname, iface, state)
|
||||
switch (state) {
|
||||
case "DISCONNECTED":
|
||||
case "AUTHENTICATING":
|
||||
case "SCANNING":
|
||||
msg.up = false;
|
||||
break;
|
||||
case "INTERFACE_DISABLED":
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From: Harshitha Prem <quic_hprem@quicinc.com>
|
||||
Date: Wed, 22 Feb 2023 09:29:01 +0530
|
||||
Subject: [PATCH] nl80211: Add frequency info in start AP command
|
||||
|
||||
When ACS is configured in multiple BSS case, sometimes a virtual AP
|
||||
interface does not come up as the channel context information between
|
||||
different BSSs of the same band does not match.
|
||||
|
||||
Same behavior is observed in case of multiple band/hardware under a
|
||||
single wiphy, when we bring up multiple virtual interface in various
|
||||
bands simultaneously and the kernel maps a random channel as it has more
|
||||
than one channel context, e.g., say a 2.4 GHz channel to a 5 GHz virtual
|
||||
AP interface when the start AP command is sent. This is because the
|
||||
frequency information is not present in the command.
|
||||
|
||||
Add the frequency information into the start AP netlink command so that
|
||||
the kernel maps the appropriate channel context by parsing it instead of
|
||||
using a previous set channel information.
|
||||
|
||||
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -167,6 +167,8 @@ static int nl80211_send_frame_cmd(struct
|
||||
const u16 *csa_offs, size_t csa_offs_len);
|
||||
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
|
||||
int report);
|
||||
+static int nl80211_put_freq_params(struct nl_msg *msg,
|
||||
+ const struct hostapd_freq_params *freq);
|
||||
|
||||
#define IFIDX_ANY -1
|
||||
|
||||
@@ -4717,6 +4719,9 @@ static int wpa_driver_nl80211_set_ap(voi
|
||||
nla_nest_end(msg, spr);
|
||||
}
|
||||
|
||||
+ if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
if (params->freq && params->freq->he_enabled) {
|
||||
struct nlattr *bss_color;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 10:53:50 +0200
|
||||
Subject: [PATCH] driver_nl80211: fix setting QoS map on secondary BSSs
|
||||
|
||||
The setting is per-BSS, not per PHY
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -10045,7 +10045,7 @@ static int nl80211_set_qos_map(void *pri
|
||||
wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
|
||||
qos_map_set, qos_map_set_len);
|
||||
|
||||
- if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) ||
|
||||
+ if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_QOS_MAP)) ||
|
||||
nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
@@ -0,0 +1,18 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 11:28:03 +0200
|
||||
Subject: [PATCH] driver_nl80211: update drv->ifindex on removing the first
|
||||
BSS
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -8003,6 +8003,7 @@ static int wpa_driver_nl80211_if_remove(
|
||||
if (drv->first_bss->next) {
|
||||
drv->first_bss = drv->first_bss->next;
|
||||
drv->ctx = drv->first_bss->ctx;
|
||||
+ drv->ifindex = drv->first_bss->ifindex;
|
||||
os_free(bss);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
|
||||
@@ -1,5 +1,7 @@
|
||||
--- a/hostapd/Makefile
|
||||
+++ b/hostapd/Makefile
|
||||
Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/hostapd/Makefile
|
||||
+++ hostapd-2021-02-20-59e9794c/hostapd/Makefile
|
||||
@@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common
|
||||
|
||||
OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
||||
@@ -13,8 +15,10 @@
|
||||
|
||||
ifdef CONFIG_CODE_COVERAGE
|
||||
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
|
||||
--- a/src/ap/hostapd.h
|
||||
+++ b/src/ap/hostapd.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "utils/list.h"
|
||||
#include "ap_config.h"
|
||||
@@ -39,8 +43,10 @@
|
||||
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||
struct hostapd_iface * hostapd_alloc_iface(void);
|
||||
--- a/src/ap/hostapd.c
|
||||
+++ b/src/ap/hostapd.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
||||
@@ -376,6 +376,7 @@ void hostapd_free_hapd_data(struct hosta
|
||||
hapd->beacon_set_done = 0;
|
||||
|
||||
@@ -82,8 +88,10 @@
|
||||
hostapd_interface_deinit(iface);
|
||||
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
||||
__func__, driver, drv_priv);
|
||||
--- a/src/ap/ieee802_11.c
|
||||
+++ b/src/ap/ieee802_11.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_11.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c
|
||||
@@ -3421,13 +3421,18 @@ static void handle_auth(struct hostapd_d
|
||||
u16 auth_alg, auth_transaction, status_code;
|
||||
u16 resp = WLAN_STATUS_SUCCESS;
|
||||
@@ -170,8 +178,10 @@
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
if (sta == NULL) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
|
||||
--- a/src/ap/beacon.c
|
||||
+++ b/src/ap/beacon.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
||||
@@ -823,6 +823,12 @@ void handle_probe_req(struct hostapd_dat
|
||||
u16 csa_offs[2];
|
||||
size_t csa_offs_len;
|
||||
@@ -198,8 +208,10 @@
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
|
||||
--- a/src/ap/drv_callbacks.c
|
||||
+++ b/src/ap/drv_callbacks.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/drv_callbacks.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c
|
||||
@@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d
|
||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||
int status = WLAN_STATUS_SUCCESS;
|
||||
@@ -224,8 +236,22 @@
|
||||
#ifdef CONFIG_P2P
|
||||
if (elems.p2p) {
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
--- a/src/ap/sta_info.c
|
||||
+++ b/src/ap/sta_info.c
|
||||
@@ -981,9 +991,11 @@ void hostapd_event_ch_switch(struct host
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||
"freq=%d dfs=%d", freq, is_dfs);
|
||||
+ hostapd_ubus_notify_csa(hapd, freq);
|
||||
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||
"freq=%d dfs=%d", freq, is_dfs);
|
||||
+ hostapd_ubus_notify_csa(hapd, freq);
|
||||
} else if (is_dfs &&
|
||||
hostapd_is_dfs_required(hapd->iface) &&
|
||||
!hostapd_is_dfs_chan_available(hapd->iface) &&
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
||||
@@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
@@ -304,8 +330,10 @@
|
||||
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
--- a/src/ap/wpa_auth_glue.c
|
||||
+++ b/src/ap/wpa_auth_glue.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_glue.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c
|
||||
@@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure
|
||||
struct hostapd_data *hapd = ctx;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
|
||||
@@ -314,8 +342,10 @@
|
||||
}
|
||||
|
||||
|
||||
--- a/wpa_supplicant/Makefile
|
||||
+++ b/wpa_supplicant/Makefile
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/Makefile
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile
|
||||
@@ -169,6 +169,13 @@ ifdef CONFIG_EAPOL_TEST
|
||||
CFLAGS += -Werror -DEAPOL_TEST
|
||||
endif
|
||||
@@ -340,8 +370,10 @@
|
||||
endif
|
||||
|
||||
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
|
||||
--- a/wpa_supplicant/wpa_supplicant.c
|
||||
+++ b/wpa_supplicant/wpa_supplicant.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c
|
||||
@@ -6943,6 +6943,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
@@ -373,8 +405,10 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/wpa_supplicant/wpa_supplicant_i.h
|
||||
+++ b/wpa_supplicant/wpa_supplicant_i.h
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant_i.h
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "wps/wps_defs.h"
|
||||
#include "config_ssid.h"
|
||||
@@ -400,8 +434,10 @@
|
||||
#ifdef CONFIG_MATCH_IFACE
|
||||
int matched;
|
||||
#endif /* CONFIG_MATCH_IFACE */
|
||||
--- a/wpa_supplicant/wps_supplicant.c
|
||||
+++ b/wpa_supplicant/wps_supplicant.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wps_supplicant.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "p2p/p2p.h"
|
||||
#include "p2p_supplicant.h"
|
||||
@@ -419,8 +455,10 @@
|
||||
if (wpa_s->conf->wps_cred_processing == 1)
|
||||
return 0;
|
||||
|
||||
--- a/wpa_supplicant/main.c
|
||||
+++ b/wpa_supplicant/main.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/main.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c
|
||||
@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (;;) {
|
||||
@@ -440,8 +478,10 @@
|
||||
case 'o':
|
||||
params.override_driver = optarg;
|
||||
break;
|
||||
--- a/src/ap/rrm.c
|
||||
+++ b/src/ap/rrm.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/rrm.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/rrm.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/rrm.c
|
||||
@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report
|
||||
return;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
|
||||
@@ -452,8 +492,10 @@
|
||||
}
|
||||
|
||||
|
||||
--- a/src/ap/vlan_init.c
|
||||
+++ b/src/ap/vlan_init.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
|
||||
@@ -22,6 +22,7 @@
|
||||
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||
int existsok)
|
||||
@@ -490,8 +532,10 @@
|
||||
return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||
}
|
||||
|
||||
--- a/src/ap/dfs.c
|
||||
+++ b/src/ap/dfs.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/dfs.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/dfs.c
|
||||
@@ -1226,6 +1226,8 @@ int hostapd_dfs_nop_finished(struct host
|
||||
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
||||
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
||||
@@ -501,8 +545,10 @@
|
||||
/* Proceed only if DFS is not offloaded to the driver */
|
||||
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
||||
return 0;
|
||||
--- a/src/ap/airtime_policy.c
|
||||
+++ b/src/ap/airtime_policy.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/airtime_policy.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c
|
||||
@@ -108,8 +108,14 @@ static void set_sta_weights(struct hosta
|
||||
{
|
||||
struct sta_info *sta;
|
||||
@@ -532,8 +578,10 @@
|
||||
if (weight)
|
||||
return sta_set_airtime_weight(hapd, sta, weight);
|
||||
}
|
||||
--- a/src/ap/sta_info.h
|
||||
+++ b/src/ap/sta_info.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
||||
@@ -323,6 +323,7 @@ struct sta_info {
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
@@ -542,8 +590,10 @@
|
||||
struct os_reltime backlogged_until;
|
||||
#endif /* CONFIG_AIRTIME_POLICY */
|
||||
|
||||
--- a/src/ap/wnm_ap.c
|
||||
+++ b/src/ap/wnm_ap.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wnm_ap.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c
|
||||
@@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt
|
||||
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||
pos, end - pos);
|
||||
@@ -582,8 +632,10 @@
|
||||
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||
pos, end - pos);
|
||||
}
|
||||
--- a/src/utils/eloop.c
|
||||
+++ b/src/utils/eloop.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.c
|
||||
@@ -77,6 +77,9 @@ struct eloop_sock_table {
|
||||
struct eloop_data {
|
||||
int max_sock;
|
||||
@@ -632,8 +684,10 @@
|
||||
|
||||
void eloop_terminate(void)
|
||||
{
|
||||
--- a/src/utils/eloop.h
|
||||
+++ b/src/utils/eloop.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.h
|
||||
@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo
|
||||
*/
|
||||
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
|
||||
@@ -663,8 +717,10 @@
|
||||
/**
|
||||
* eloop_run - Start the event loop
|
||||
*
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/uloop.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/src/utils/uloop.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/uloop.c
|
||||
@@ -0,0 +1,64 @@
|
||||
+#include <libubox/uloop.h>
|
||||
+#include "includes.h"
|
||||
|
||||
@@ -287,7 +287,33 @@
|
||||
|
||||
--- a/src/drivers/driver.h
|
||||
+++ b/src/drivers/driver.h
|
||||
@@ -5827,6 +5827,7 @@ union wpa_event_data {
|
||||
@@ -3357,6 +3357,25 @@ struct wpa_driver_ops {
|
||||
const char *ifname);
|
||||
|
||||
/**
|
||||
+ * if_rename - Rename a virtual interface
|
||||
+ * @priv: Private driver interface data
|
||||
+ * @type: Interface type
|
||||
+ * @ifname: Interface name of the virtual interface to be renamed
|
||||
+ * (NULL when renaming the AP BSS interface)
|
||||
+ * @new_name: New interface name of the virtual interface
|
||||
+ * Returns: 0 on success, -1 on failure
|
||||
+ */
|
||||
+ int (*if_rename)(void *priv, enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name);
|
||||
+
|
||||
+ /**
|
||||
+ * set_first_bss - Make a virtual interface the first (primary) bss
|
||||
+ * @priv: Private driver interface data
|
||||
+ * Returns: 0 on success, -1 on failure
|
||||
+ */
|
||||
+ int (*set_first_bss)(void *priv);
|
||||
+
|
||||
+ /**
|
||||
* set_sta_vlan - Bind a station into a specific interface (AP only)
|
||||
* @priv: Private driver interface data
|
||||
* @ifname: Interface (main or virtual BSS or VLAN)
|
||||
@@ -5827,6 +5846,7 @@ union wpa_event_data {
|
||||
|
||||
/**
|
||||
* struct ch_switch
|
||||
@@ -295,7 +321,7 @@
|
||||
* @freq: Frequency of new channel in MHz
|
||||
* @ht_enabled: Whether this is an HT channel
|
||||
* @ch_offset: Secondary channel offset
|
||||
@@ -5835,6 +5836,7 @@ union wpa_event_data {
|
||||
@@ -5835,6 +5855,7 @@ union wpa_event_data {
|
||||
* @cf2: Center frequency 2
|
||||
*/
|
||||
struct ch_switch {
|
||||
@@ -348,3 +374,187 @@
|
||||
switch (event) {
|
||||
case EVENT_AUTH:
|
||||
#ifdef CONFIG_FST
|
||||
--- a/src/ap/ap_drv_ops.h
|
||||
+++ b/src/ap/ap_drv_ops.h
|
||||
@@ -367,6 +367,23 @@ static inline int hostapd_drv_stop_ap(st
|
||||
return hapd->driver->stop_ap(hapd->drv_priv);
|
||||
}
|
||||
|
||||
+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
|
||||
+ enum wpa_driver_if_type type,
|
||||
+ const char *ifname,
|
||||
+ const char *new_name)
|
||||
+{
|
||||
+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
|
||||
+ return -1;
|
||||
+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
|
||||
+}
|
||||
+
|
||||
+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
|
||||
+{
|
||||
+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
|
||||
+ return 0;
|
||||
+ return hapd->driver->set_first_bss(hapd->drv_priv);
|
||||
+}
|
||||
+
|
||||
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
|
||||
struct wpa_channel_info *ci)
|
||||
{
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -1222,7 +1222,7 @@ static void wpa_driver_nl80211_event_rtm
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
|
||||
namebuf, ifname);
|
||||
- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
|
||||
+ if (drv->first_bss->ifindex != ifi->ifi_index) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Not the main interface (%s) - do not indicate interface down",
|
||||
drv->first_bss->ifname);
|
||||
@@ -1258,7 +1258,7 @@ static void wpa_driver_nl80211_event_rtm
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
|
||||
namebuf, ifname);
|
||||
- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
|
||||
+ if (drv->first_bss->ifindex != ifi->ifi_index) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Not the main interface (%s) - do not indicate interface up",
|
||||
drv->first_bss->ifname);
|
||||
@@ -7609,6 +7609,7 @@ static void *i802_init(struct hostapd_da
|
||||
char master_ifname[IFNAMSIZ];
|
||||
int ifindex, br_ifindex = 0;
|
||||
int br_added = 0;
|
||||
+ int err;
|
||||
|
||||
bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
|
||||
params->global_priv, 1,
|
||||
@@ -7668,21 +7669,17 @@ static void *i802_init(struct hostapd_da
|
||||
(params->num_bridge == 0 || !params->bridge[0]))
|
||||
add_ifidx(drv, br_ifindex, drv->ifindex);
|
||||
|
||||
- if (bss->added_if_into_bridge || bss->already_in_bridge) {
|
||||
- int err;
|
||||
-
|
||||
- drv->rtnl_sk = nl_socket_alloc();
|
||||
- if (drv->rtnl_sk == NULL) {
|
||||
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
|
||||
- goto failed;
|
||||
- }
|
||||
+ drv->rtnl_sk = nl_socket_alloc();
|
||||
+ if (drv->rtnl_sk == NULL) {
|
||||
+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
|
||||
+ goto failed;
|
||||
+ }
|
||||
|
||||
- err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
|
||||
- if (err) {
|
||||
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
|
||||
- nl_geterror(err));
|
||||
- goto failed;
|
||||
- }
|
||||
+ err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
|
||||
+ if (err) {
|
||||
+ wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
|
||||
+ nl_geterror(err));
|
||||
+ goto failed;
|
||||
}
|
||||
|
||||
if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
|
||||
@@ -8041,6 +8038,50 @@ static int wpa_driver_nl80211_if_remove(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int wpa_driver_nl80211_if_rename(struct i802_bss *bss,
|
||||
+ enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name)
|
||||
+{
|
||||
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
+ struct ifinfomsg ifi = {
|
||||
+ .ifi_family = AF_UNSPEC,
|
||||
+ .ifi_index = bss->ifindex,
|
||||
+ };
|
||||
+ struct nl_msg *msg;
|
||||
+ int res = -ENOMEM;
|
||||
+
|
||||
+ if (ifname)
|
||||
+ ifi.ifi_index = if_nametoindex(ifname);
|
||||
+
|
||||
+ msg = nlmsg_alloc_simple(RTM_SETLINK, 0);
|
||||
+ if (!msg)
|
||||
+ return res;
|
||||
+
|
||||
+ if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (nla_put_string(msg, IFLA_IFNAME, new_name))
|
||||
+ goto out;
|
||||
+
|
||||
+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
|
||||
+ if (res < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ res = nl_wait_for_ack(drv->rtnl_sk);
|
||||
+ if (res) {
|
||||
+ wpa_printf(MSG_INFO,
|
||||
+ "nl80211: Renaming device %s to %s failed: %s",
|
||||
+ ifname ? ifname : bss->ifname, new_name, nl_geterror(res));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (type == WPA_IF_AP_BSS && !ifname)
|
||||
+ os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname));
|
||||
+
|
||||
+out:
|
||||
+ nlmsg_free(msg);
|
||||
+ return res;
|
||||
+}
|
||||
|
||||
static int cookie_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
@@ -9385,6 +9426,37 @@ static int driver_nl80211_if_remove(void
|
||||
}
|
||||
|
||||
|
||||
+static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name)
|
||||
+{
|
||||
+ struct i802_bss *bss = priv;
|
||||
+ return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int driver_nl80211_set_first_bss(void *priv)
|
||||
+{
|
||||
+ struct i802_bss *bss = priv, *tbss;
|
||||
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
+
|
||||
+ if (drv->first_bss == bss)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
|
||||
+ if (tbss->next != bss)
|
||||
+ continue;
|
||||
+
|
||||
+ tbss->next = bss->next;
|
||||
+ bss->next = drv->first_bss;
|
||||
+ drv->first_bss = bss;
|
||||
+ drv->ctx = bss->ctx;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
|
||||
size_t data_len, int noack,
|
||||
unsigned int freq,
|
||||
@@ -11967,6 +12039,8 @@ const struct wpa_driver_ops wpa_driver_n
|
||||
.set_acl = wpa_driver_nl80211_set_acl,
|
||||
.if_add = wpa_driver_nl80211_if_add,
|
||||
.if_remove = driver_nl80211_if_remove,
|
||||
+ .if_rename = driver_nl80211_if_rename,
|
||||
+ .set_first_bss = driver_nl80211_set_first_bss,
|
||||
.send_mlme = driver_nl80211_send_mlme,
|
||||
.get_hw_feature_data = nl80211_get_hw_feature_data,
|
||||
.sta_add = wpa_driver_nl80211_sta_add,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
--- a/src/ap/x_snoop.c
|
||||
+++ b/src/ap/x_snoop.c
|
||||
@@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
@@ -31,28 +31,31 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -29,13 +29,20 @@
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable proxyarp on the bridge port");
|
||||
return -1;
|
||||
@@ -52,7 +54,8 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
}
|
||||
|
||||
if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
|
||||
- 1)) {
|
||||
+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
||||
+ if (!conf->snoop_iface[0] &&
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, NULL, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable multicast snooping on the bridge");
|
||||
return -1;
|
||||
@@ -44,15 +51,27 @@
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
struct l2_packet_data *l2;
|
||||
+ const char *ifname = conf->bridge;
|
||||
|
||||
- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
+
|
||||
+ if (conf->snoop_iface[0])
|
||||
+ ifname = conf->snoop_iface;
|
||||
+
|
||||
|
||||
- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
+ l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
if (l2 == NULL) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to initialize L2 packet processing %s",
|
||||
@@ -125,7 +132,10 @@ void x_snoop_mcast_to_ucast_convert_send
|
||||
|
||||
void x_snoop_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
|
||||
+ struct hostapd_bss_config *conf = hapd->conf;
|
||||
+
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
|
||||
+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0);
|
||||
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
|
||||
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
|
||||
}
|
||||
--- a/hostapd/config_file.c
|
||||
+++ b/hostapd/config_file.c
|
||||
@@ -2343,6 +2343,8 @@ static int hostapd_config_fill(struct ho
|
||||
@@ -64,3 +83,55 @@
|
||||
} else if (os_strcmp(buf, "vlan_bridge") == 0) {
|
||||
os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
|
||||
} else if (os_strcmp(buf, "wds_bridge") == 0) {
|
||||
--- a/src/ap/ap_drv_ops.h
|
||||
+++ b/src/ap/ap_drv_ops.h
|
||||
@@ -340,12 +340,12 @@ static inline int hostapd_drv_br_port_se
|
||||
|
||||
static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
|
||||
enum drv_br_net_param param,
|
||||
- unsigned int val)
|
||||
+ const char *ifname, unsigned int val)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||
hapd->driver->br_set_net_param == NULL)
|
||||
return -1;
|
||||
- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
|
||||
+ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
||||
--- a/src/drivers/driver.h
|
||||
+++ b/src/drivers/driver.h
|
||||
@@ -3756,7 +3756,7 @@ struct wpa_driver_ops {
|
||||
* Returns: 0 on success, negative (<0) on failure
|
||||
*/
|
||||
int (*br_set_net_param)(void *priv, enum drv_br_net_param param,
|
||||
- unsigned int val);
|
||||
+ const char *ifname, unsigned int val);
|
||||
|
||||
/**
|
||||
* get_wowlan - Get wake-on-wireless status
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -10825,7 +10825,7 @@ static const char * drv_br_net_param_str
|
||||
|
||||
|
||||
static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
|
||||
- unsigned int val)
|
||||
+ const char *ifname, unsigned int val)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
char path[128];
|
||||
@@ -10851,8 +10851,11 @@ static int wpa_driver_br_set_net_param(v
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if (!ifname)
|
||||
+ ifname = bss->brname;
|
||||
+
|
||||
os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
|
||||
- ip_version, bss->brname, param_txt);
|
||||
+ ip_version, ifname, param_txt);
|
||||
|
||||
set_val:
|
||||
if (linux_write_system_file(path, val))
|
||||
|
||||
@@ -19,18 +19,6 @@
|
||||
|
||||
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -424,6 +424,9 @@ hostapd_bss_get_status(struct ubus_conte
|
||||
hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
||||
blobmsg_close_table(&b, dfs_table);
|
||||
|
||||
+ if (hapd->conf->uci_section)
|
||||
+ blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
+
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
--- a/src/ap/ap_config.c
|
||||
+++ b/src/ap/ap_config.c
|
||||
@@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host
|
||||
|
||||
@@ -50,42 +50,4 @@
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -306,6 +306,36 @@ hostapd_bss_get_clients(struct ubus_cont
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
|
||||
blobmsg_close_table(&b, r);
|
||||
blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
|
||||
+
|
||||
+ r = blobmsg_open_table(&b, "mcs");
|
||||
+ if (sta_driver_data.rx_hemcs) {
|
||||
+ blobmsg_add_u32(&b, "he", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs);
|
||||
+ } else if (sta_driver_data.rx_vhtmcs) {
|
||||
+ blobmsg_add_u32(&b, "vht", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs);
|
||||
+ } else {
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
+ }
|
||||
+ blobmsg_close_table(&b, r);
|
||||
+
|
||||
+ r = blobmsg_open_table(&b, "nss");
|
||||
+ if (sta_driver_data.rx_he_nss) {
|
||||
+ blobmsg_add_u32(&b, "he", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss);
|
||||
+ } else if (sta_driver_data.rx_vht_nss) {
|
||||
+ blobmsg_add_u32(&b, "vht", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss);
|
||||
+ } else {
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
+ }
|
||||
+ blobmsg_close_table(&b, r);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
|
||||
|
||||
48
feeds/ipq807x_v5.4/hostapd/patches/999-ft-anonce.patch
Normal file
48
feeds/ipq807x_v5.4/hostapd/patches/999-ft-anonce.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_ft.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c
|
||||
@@ -3067,6 +3067,7 @@ static int wpa_ft_process_auth_req(struc
|
||||
size_t identity_len = 0, radius_cui_len = 0;
|
||||
int use_sha384;
|
||||
size_t pmk_r1_len, kdk_len;
|
||||
+ struct os_reltime now;
|
||||
|
||||
*resp_ies = NULL;
|
||||
*resp_ies_len = 0;
|
||||
@@ -3185,10 +3186,19 @@ pmk_r1_derived:
|
||||
os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len);
|
||||
sm->pmk_r1_len = pmk_r1_len;
|
||||
|
||||
- if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
- wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
- "ANonce");
|
||||
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
+ if (os_get_reltime(&now) < 0 ||
|
||||
+ os_reltime_expired(&now, &sm->ANonce_time, 1)) {
|
||||
+ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
+ wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
+ "ANonce");
|
||||
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
+ }
|
||||
+ sm->ANonce_time.sec = now.sec;
|
||||
+ sm->ANonce_time.usec = now.usec;
|
||||
+ wpa_printf(MSG_INFO, "FT: ANonce was randomized");
|
||||
+ } else {
|
||||
+ wpa_printf(MSG_INFO, "FT: ANonce has not expired");
|
||||
+
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_i.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h
|
||||
@@ -54,6 +54,7 @@ struct wpa_state_machine {
|
||||
bool MICVerified;
|
||||
bool GUpdateStationKeys;
|
||||
u8 ANonce[WPA_NONCE_LEN];
|
||||
+ struct os_reltime ANonce_time;
|
||||
u8 SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
@@ -61,28 +61,6 @@
|
||||
};
|
||||
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -336,6 +336,9 @@ hostapd_bss_get_clients(struct ubus_cont
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
+
|
||||
+ if (sta->signal_mgmt)
|
||||
+ blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
@@ -457,6 +460,9 @@ hostapd_bss_get_status(struct ubus_conte
|
||||
if (hapd->conf->uci_section)
|
||||
blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
|
||||
+ if (hapd->signal_mgmt)
|
||||
+ blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt);
|
||||
+
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
--- a/src/ap/hostapd.h
|
||||
+++ b/src/ap/hostapd.h
|
||||
@@ -451,6 +451,7 @@ struct hostapd_data {
|
||||
|
||||
@@ -306,6 +306,39 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
|
||||
blobmsg_close_table(&b, r);
|
||||
blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
|
||||
|
||||
r = blobmsg_open_table(&b, "mcs");
|
||||
if (sta_driver_data.rx_hemcs) {
|
||||
blobmsg_add_u32(&b, "he", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs);
|
||||
} else if (sta_driver_data.rx_vhtmcs) {
|
||||
blobmsg_add_u32(&b, "vht", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs);
|
||||
} else {
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
|
||||
r = blobmsg_open_table(&b, "nss");
|
||||
if (sta_driver_data.rx_he_nss) {
|
||||
blobmsg_add_u32(&b, "he", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss);
|
||||
} else if (sta_driver_data.rx_vht_nss) {
|
||||
blobmsg_add_u32(&b, "vht", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss);
|
||||
} else {
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
|
||||
if (sta->signal_mgmt)
|
||||
blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
@@ -424,6 +457,12 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
||||
blobmsg_close_table(&b, dfs_table);
|
||||
|
||||
if (hapd->conf->uci_section)
|
||||
blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
|
||||
if (hapd->signal_mgmt)
|
||||
blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt);
|
||||
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
@@ -1698,6 +1737,19 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *
|
||||
ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
|
||||
}
|
||||
|
||||
void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq)
|
||||
{
|
||||
if (!hapd->ubus.obj.has_subscribers)
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "ifname", hapd->conf->iface);
|
||||
blobmsg_add_u32(&b, "freq", freq);
|
||||
blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
|
||||
|
||||
ubus_notify(ctx, &hapd->ubus.obj, "channel-switch", b.head, -1);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
|
||||
1845
feeds/ipq807x_v5.4/hostapd/src/src/ap/ubus.c.orig
Normal file
1845
feeds/ipq807x_v5.4/hostapd/src/src/ap/ubus.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@ void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
||||
int hostapd_ubus_notify_bss_transition_query(
|
||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
||||
const u8 *candidate_list, u16 candidate_list_len);
|
||||
void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "beacon.h"
|
||||
#include "hw_features.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "dfs.h"
|
||||
#include "acs.h"
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
static uc_resource_type_t *global_type, *bss_type, *iface_type;
|
||||
@@ -109,6 +111,94 @@ uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct hostapd_vlan *
|
||||
bss_conf_find_vlan(struct hostapd_bss_config *bss, int id)
|
||||
{
|
||||
struct hostapd_vlan *vlan;
|
||||
|
||||
for (vlan = bss->vlan; vlan; vlan = vlan->next)
|
||||
if (vlan->vlan_id == id)
|
||||
return vlan;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
bss_conf_rename_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||
const char *ifname)
|
||||
{
|
||||
if (!strcmp(ifname, vlan->ifname))
|
||||
return 0;
|
||||
|
||||
hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, vlan->ifname, ifname);
|
||||
os_strlcpy(vlan->ifname, ifname, sizeof(vlan->ifname));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bss_reload_vlans(struct hostapd_data *hapd, struct hostapd_bss_config *bss)
|
||||
{
|
||||
struct hostapd_bss_config *old_bss = hapd->conf;
|
||||
struct hostapd_vlan *vlan, *vlan_new, *wildcard;
|
||||
char ifname[IFNAMSIZ + 1], vlan_ifname[IFNAMSIZ + 1], *pos;
|
||||
int ret;
|
||||
|
||||
vlan = bss_conf_find_vlan(old_bss, VLAN_ID_WILDCARD);
|
||||
wildcard = bss_conf_find_vlan(bss, VLAN_ID_WILDCARD);
|
||||
if (!!vlan != !!wildcard)
|
||||
return -1;
|
||||
|
||||
if (vlan && wildcard && strcmp(vlan->ifname, wildcard->ifname) != 0)
|
||||
strcpy(vlan->ifname, wildcard->ifname);
|
||||
else
|
||||
wildcard = NULL;
|
||||
|
||||
for (vlan = bss->vlan; vlan; vlan = vlan->next) {
|
||||
if (vlan->vlan_id == VLAN_ID_WILDCARD ||
|
||||
vlan->dynamic_vlan > 0)
|
||||
continue;
|
||||
|
||||
if (!bss_conf_find_vlan(old_bss, vlan->vlan_id))
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (vlan = old_bss->vlan; vlan; vlan = vlan->next) {
|
||||
if (vlan->vlan_id == VLAN_ID_WILDCARD)
|
||||
continue;
|
||||
|
||||
if (vlan->dynamic_vlan == 0) {
|
||||
vlan_new = bss_conf_find_vlan(bss, vlan->vlan_id);
|
||||
if (!vlan_new)
|
||||
return -1;
|
||||
|
||||
if (bss_conf_rename_vlan(hapd, vlan, vlan_new->ifname))
|
||||
return -1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!wildcard)
|
||||
continue;
|
||||
|
||||
os_strlcpy(ifname, wildcard->ifname, sizeof(ifname));
|
||||
pos = os_strchr(ifname, '#');
|
||||
if (!pos)
|
||||
return -1;
|
||||
|
||||
*pos++ = '\0';
|
||||
ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s%d%s",
|
||||
ifname, vlan->vlan_id, pos);
|
||||
if (os_snprintf_error(sizeof(vlan_ifname), ret))
|
||||
return -1;
|
||||
|
||||
if (bss_conf_rename_vlan(hapd, vlan, vlan_ifname))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
@@ -118,6 +208,7 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_config *conf;
|
||||
uc_value_t *file = uc_fn_arg(0);
|
||||
uc_value_t *index = uc_fn_arg(1);
|
||||
uc_value_t *files_only = uc_fn_arg(2);
|
||||
unsigned int i, idx = 0;
|
||||
int ret = -1;
|
||||
|
||||
@@ -129,9 +220,28 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
|
||||
iface = hapd->iface;
|
||||
conf = interfaces->config_read_cb(ucv_string_get(file));
|
||||
if (!conf || idx > conf->num_bss || !conf->bss[idx])
|
||||
if (!conf)
|
||||
goto out;
|
||||
|
||||
if (idx > conf->num_bss || !conf->bss[idx])
|
||||
goto free;
|
||||
|
||||
if (ucv_boolean_get(files_only)) {
|
||||
struct hostapd_bss_config *bss = conf->bss[idx];
|
||||
struct hostapd_bss_config *old_bss = hapd->conf;
|
||||
|
||||
#define swap_field(name) \
|
||||
do { \
|
||||
void *ptr = old_bss->name; \
|
||||
old_bss->name = bss->name; \
|
||||
bss->name = ptr; \
|
||||
} while (0)
|
||||
|
||||
swap_field(ssid.wpa_psk_file);
|
||||
ret = bss_reload_vlans(hapd, bss);
|
||||
goto done;
|
||||
}
|
||||
|
||||
hostapd_bss_deinit_no_free(hapd);
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hostapd_free_hapd_data(hapd);
|
||||
@@ -142,12 +252,14 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
iface->conf->bss[i] = conf->bss[idx];
|
||||
hapd->conf = conf->bss[idx];
|
||||
conf->bss[idx] = old_bss;
|
||||
hostapd_config_free(conf);
|
||||
|
||||
hostapd_setup_bss(hapd, hapd == iface->bss[0], !iface->conf->multiple_bssid);
|
||||
hostapd_setup_bss(hapd, hapd == iface->bss[0], true);
|
||||
hostapd_ucode_update_interfaces();
|
||||
|
||||
done:
|
||||
ret = 0;
|
||||
|
||||
free:
|
||||
hostapd_config_free(conf);
|
||||
out:
|
||||
return ucv_int64_new(ret);
|
||||
}
|
||||
@@ -178,10 +290,15 @@ uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface;
|
||||
int i, idx;
|
||||
|
||||
if (!hapd || hapd == hapd->iface->bss[0])
|
||||
if (!hapd)
|
||||
return NULL;
|
||||
|
||||
iface = hapd->iface;
|
||||
if (iface->num_bss == 1) {
|
||||
wpa_printf(MSG_ERROR, "trying to delete last bss of an iface: %s\n", hapd->conf->iface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < iface->num_bss; idx++)
|
||||
if (iface->bss[idx] == hapd)
|
||||
break;
|
||||
@@ -191,8 +308,13 @@ uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
|
||||
|
||||
for (i = idx + 1; i < iface->num_bss; i++)
|
||||
iface->bss[i - 1] = iface->bss[i];
|
||||
|
||||
iface->num_bss--;
|
||||
|
||||
iface->bss[0]->interface_added = 0;
|
||||
hostapd_drv_set_first_bss(iface->bss[0]);
|
||||
hapd->interface_added = 1;
|
||||
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hostapd_bss_deinit(hapd);
|
||||
hostapd_remove_iface_bss_conf(iface->conf, hapd->conf);
|
||||
@@ -266,6 +388,58 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_iface_set_bss_order(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
uc_value_t *bss_list = uc_fn_arg(0);
|
||||
struct hostapd_data **new_bss;
|
||||
struct hostapd_bss_config **new_conf;
|
||||
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
||||
if (ucv_type(bss_list) != UC_ARRAY ||
|
||||
ucv_array_length(bss_list) != iface->num_bss)
|
||||
return NULL;
|
||||
|
||||
new_bss = calloc(iface->num_bss, sizeof(*new_bss));
|
||||
new_conf = calloc(iface->num_bss, sizeof(*new_conf));
|
||||
for (size_t i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *bss;
|
||||
|
||||
bss = ucv_resource_data(ucv_array_get(bss_list, i), "hostapd.bss");
|
||||
if (bss->iface != iface)
|
||||
goto free;
|
||||
|
||||
for (size_t k = 0; k < i; k++)
|
||||
if (new_bss[k] == bss)
|
||||
goto free;
|
||||
|
||||
new_bss[i] = bss;
|
||||
new_conf[i] = bss->conf;
|
||||
}
|
||||
|
||||
new_bss[0]->interface_added = 0;
|
||||
for (size_t i = 1; i < iface->num_bss; i++)
|
||||
new_bss[i]->interface_added = 1;
|
||||
|
||||
free(iface->bss);
|
||||
iface->bss = new_bss;
|
||||
|
||||
free(iface->conf->bss);
|
||||
iface->conf->bss = new_conf;
|
||||
iface->conf->num_bss = iface->num_bss;
|
||||
hostapd_drv_set_first_bss(iface->bss[0]);
|
||||
|
||||
return ucv_boolean_new(true);
|
||||
|
||||
free:
|
||||
free(new_bss);
|
||||
free(new_conf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
@@ -297,12 +471,32 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
int i;
|
||||
|
||||
switch (iface->state) {
|
||||
case HAPD_IFACE_ENABLED:
|
||||
case HAPD_IFACE_DISABLED:
|
||||
break;
|
||||
#ifdef CONFIG_ACS
|
||||
case HAPD_IFACE_ACS:
|
||||
acs_cleanup(iface);
|
||||
iface->scan_cb = NULL;
|
||||
/* fallthrough */
|
||||
#endif
|
||||
default:
|
||||
hostapd_disable_iface(iface);
|
||||
break;
|
||||
}
|
||||
|
||||
if (iface->state != HAPD_IFACE_ENABLED)
|
||||
hostapd_disable_iface(iface);
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *hapd = iface->bss[i];
|
||||
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hapd->started = 0;
|
||||
hapd->beacon_set_done = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
@@ -311,67 +505,85 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
uc_value_t *info = uc_fn_arg(0);
|
||||
struct hostapd_config *conf;
|
||||
bool changed = false;
|
||||
uint64_t intval;
|
||||
int i;
|
||||
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
||||
if (!info)
|
||||
if (!info) {
|
||||
iface->freq = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ucv_type(info) != UC_OBJECT)
|
||||
return NULL;
|
||||
|
||||
#define UPDATE_VAL(field, name) \
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, name, NULL))) && \
|
||||
!errno && intval != conf->field) do { \
|
||||
conf->field = intval; \
|
||||
changed = true; \
|
||||
} while(0)
|
||||
|
||||
conf = iface->conf;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno)
|
||||
conf->op_class = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno)
|
||||
conf->hw_mode = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno)
|
||||
conf->channel = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
|
||||
conf->secondary_channel = intval;
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL))) && !errno) {
|
||||
conf->vht_oper_centr_freq_seg0_idx = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_centr_freq_seg0_idx = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_centr_freq_seg0_idx = intval;
|
||||
#endif
|
||||
}
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL))) && !errno) {
|
||||
conf->vht_oper_centr_freq_seg1_idx = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_centr_freq_seg1_idx = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_centr_freq_seg1_idx = intval;
|
||||
#endif
|
||||
}
|
||||
UPDATE_VAL(op_class, "op_class");
|
||||
UPDATE_VAL(hw_mode, "hw_mode");
|
||||
UPDATE_VAL(channel, "channel");
|
||||
UPDATE_VAL(secondary_channel, "sec_channel");
|
||||
if (!changed &&
|
||||
(iface->bss[0]->beacon_set_done ||
|
||||
iface->state == HAPD_IFACE_DFS))
|
||||
return ucv_boolean_new(true);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL));
|
||||
if (!errno)
|
||||
hostapd_set_oper_centr_freq_seg0_idx(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL));
|
||||
if (!errno)
|
||||
hostapd_set_oper_centr_freq_seg1_idx(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
|
||||
if (!errno) {
|
||||
conf->vht_oper_chwidth = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_chwidth = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_chwidth = intval;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (!errno)
|
||||
hostapd_set_oper_chwidth(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL));
|
||||
if (!errno)
|
||||
iface->freq = intval;
|
||||
else
|
||||
iface->freq = 0;
|
||||
conf->acs = 0;
|
||||
|
||||
out:
|
||||
if (conf->channel)
|
||||
switch (iface->state) {
|
||||
case HAPD_IFACE_DISABLED:
|
||||
break;
|
||||
case HAPD_IFACE_ENABLED:
|
||||
if (!hostapd_is_dfs_required(iface) ||
|
||||
hostapd_is_dfs_chan_available(iface))
|
||||
break;
|
||||
wpa_printf(MSG_INFO, "DFS CAC required on new channel, restart interface");
|
||||
/* fallthrough */
|
||||
default:
|
||||
hostapd_disable_iface(iface);
|
||||
break;
|
||||
}
|
||||
|
||||
if (conf->channel && !iface->freq)
|
||||
iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel);
|
||||
|
||||
if (iface->state != HAPD_IFACE_ENABLED) {
|
||||
hostapd_enable_iface(iface);
|
||||
return ucv_boolean_new(true);
|
||||
}
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *hapd = iface->bss[i];
|
||||
int ret;
|
||||
|
||||
hapd->started = 1;
|
||||
hapd->conf->start_disabled = 0;
|
||||
hostapd_set_freq(hapd, conf->hw_mode, iface->freq,
|
||||
conf->channel,
|
||||
conf->enable_edmg,
|
||||
@@ -436,6 +648,55 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
|
||||
return ucv_boolean_new(!ret);
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_rename(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss");
|
||||
uc_value_t *ifname_arg = uc_fn_arg(0);
|
||||
char prev_ifname[IFNAMSIZ + 1];
|
||||
struct sta_info *sta;
|
||||
const char *ifname;
|
||||
int ret;
|
||||
|
||||
if (!hapd || ucv_type(ifname_arg) != UC_STRING)
|
||||
return NULL;
|
||||
|
||||
os_strlcpy(prev_ifname, hapd->conf->iface, sizeof(prev_ifname));
|
||||
ifname = ucv_string_get(ifname_arg);
|
||||
|
||||
hostapd_ubus_free_bss(hapd);
|
||||
if (interfaces->ctrl_iface_deinit)
|
||||
interfaces->ctrl_iface_deinit(hapd);
|
||||
|
||||
ret = hostapd_drv_if_rename(hapd, WPA_IF_AP_BSS, NULL, ifname);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
char cur_name[IFNAMSIZ + 1], new_name[IFNAMSIZ + 1];
|
||||
|
||||
if (!(sta->flags & WLAN_STA_WDS) || sta->pending_wds_enable)
|
||||
continue;
|
||||
|
||||
snprintf(cur_name, sizeof(cur_name), "%s.sta%d", prev_ifname, sta->aid);
|
||||
snprintf(new_name, sizeof(new_name), "%s.sta%d", ifname, sta->aid);
|
||||
hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, cur_name, new_name);
|
||||
}
|
||||
|
||||
if (!strncmp(hapd->conf->ssid.vlan, hapd->conf->iface, sizeof(hapd->conf->ssid.vlan)))
|
||||
os_strlcpy(hapd->conf->ssid.vlan, ifname, sizeof(hapd->conf->ssid.vlan));
|
||||
os_strlcpy(hapd->conf->iface, ifname, sizeof(hapd->conf->iface));
|
||||
hostapd_ubus_add_bss(hapd);
|
||||
|
||||
hostapd_ucode_update_interfaces();
|
||||
out:
|
||||
if (interfaces->ctrl_iface_init)
|
||||
interfaces->ctrl_iface_init(hapd);
|
||||
|
||||
return ret ? NULL : ucv_boolean_new(true);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
||||
{
|
||||
static const uc_function_list_t global_fns[] = {
|
||||
@@ -449,9 +710,11 @@ int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
||||
static const uc_function_list_t bss_fns[] = {
|
||||
{ "ctrl", uc_hostapd_bss_ctrl },
|
||||
{ "set_config", uc_hostapd_bss_set_config },
|
||||
{ "rename", uc_hostapd_bss_rename },
|
||||
{ "delete", uc_hostapd_bss_delete },
|
||||
};
|
||||
static const uc_function_list_t iface_fns[] = {
|
||||
{ "set_bss_order", uc_hostapd_iface_set_bss_order },
|
||||
{ "add_bss", uc_hostapd_iface_add_bss },
|
||||
{ "stop", uc_hostapd_iface_stop },
|
||||
{ "start", uc_hostapd_iface_start },
|
||||
|
||||
@@ -129,7 +129,10 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
|
||||
tmp_channel &= ~((8 << width) - 1);
|
||||
center_idx = tmp_channel + center_ofs + (4 << width) - 1;
|
||||
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx));
|
||||
if (freq_val < 3000)
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(0));
|
||||
else
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx));
|
||||
center_idx = (center_idx - channel) * 5 + freq_val;
|
||||
ucv_object_add(ret, "center_freq1", ucv_int64_new(center_idx));
|
||||
|
||||
@@ -295,9 +298,15 @@ uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx)
|
||||
uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx)
|
||||
{
|
||||
uc_value_t *val = wpa_ucode_registry_get(reg, idx);
|
||||
void **dataptr;
|
||||
|
||||
if (val)
|
||||
ucv_array_set(reg, idx - 1, NULL);
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
ucv_array_set(reg, idx - 1, NULL);
|
||||
dataptr = ucv_resource_dataptr(val, NULL);
|
||||
if (dataptr)
|
||||
*dataptr = NULL;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/ucode.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "wps_supplicant.h"
|
||||
#include "bss.h"
|
||||
@@ -211,12 +212,13 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
|
||||
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
|
||||
if (ie && ie[1] >= 2) {
|
||||
const struct ieee80211_ht_operation *ht_oper;
|
||||
int sec;
|
||||
|
||||
ht_oper = (const void *) (ie + 2);
|
||||
if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
sec = ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
|
||||
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
sec_chan = 1;
|
||||
else if (ht_oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
sec_chan = -1;
|
||||
}
|
||||
|
||||
@@ -224,6 +226,15 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
|
||||
ucv_object_add(ret, "frequency", ucv_int64_new(bss->freq));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
if (wpa_s->ifmsh) {
|
||||
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
|
||||
|
||||
ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(ifmsh->conf->secondary_channel));
|
||||
ucv_object_add(ret, "frequency", ucv_int64_new(ifmsh->freq));
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ DEFAULT_PACKAGES += kmod-qca-nss-dp kmod-qca-ssdk swconfig \
|
||||
kmod-usb-phy-ipq5018 kmod-usb-dwc3-qcom-internal \
|
||||
kmod-ath11k-ahb ath11k-firmware-ipq5018 \
|
||||
kmod-gpio-button-hotplug iwinfo \
|
||||
qca-ssdk-shell kmod-qca-nss-drv-bridge-mgr \
|
||||
qca-ssdk-shell \
|
||||
uboot-envtools
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From: Andy Ren <andy.ren@getcruise.com>
|
||||
Date: Mon, 7 Nov 2022 09:42:42 -0800
|
||||
Subject: [PATCH] net/core: Allow live renaming when an interface is up
|
||||
|
||||
Allow a network interface to be renamed when the interface
|
||||
is up.
|
||||
|
||||
As described in the netconsole documentation [1], when netconsole is
|
||||
used as a built-in, it will bring up the specified interface as soon as
|
||||
possible. As a result, user space will not be able to rename the
|
||||
interface since the kernel disallows renaming of interfaces that are
|
||||
administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set
|
||||
by the kernel.
|
||||
|
||||
The original solution [2] to this problem was to add a new parameter to
|
||||
the netconsole configuration parameters that allows renaming of
|
||||
the interface used by netconsole while it is administratively up.
|
||||
However, during the discussion that followed, it became apparent that we
|
||||
have no reason to keep the current restriction and instead we should
|
||||
allow user space to rename interfaces regardless of their administrative
|
||||
state:
|
||||
|
||||
1. The restriction was put in place over 20 years ago when renaming was
|
||||
only possible via IOCTL and before rtnetlink started notifying user
|
||||
space about such changes like it does today.
|
||||
|
||||
2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version
|
||||
5.2 and no regressions were reported.
|
||||
|
||||
3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about
|
||||
the administrative state of interface.
|
||||
|
||||
Therefore, allow user space to rename running interfaces by removing the
|
||||
restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in
|
||||
possible triage by emitting a message to the kernel log that an
|
||||
interface was renamed while UP.
|
||||
|
||||
[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst
|
||||
[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/
|
||||
|
||||
Signed-off-by: Andy Ren <andy.ren@getcruise.com>
|
||||
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||||
Reviewed-by: David Ahern <dsahern@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
===================================================================
|
||||
--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/core/dev.c
|
||||
+++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
@@ -1125,7 +1125,8 @@ int dev_change_name(struct net_device *d
|
||||
}
|
||||
|
||||
if (oldname[0] && !strchr(oldname, '%'))
|
||||
- netdev_info(dev, "renamed from %s\n", oldname);
|
||||
+ netdev_info(dev, "renamed from %s%s\n", oldname,
|
||||
+ dev->flags & IFF_UP ? " (while UP)" : "");
|
||||
|
||||
old_assign_type = dev->name_assign_type;
|
||||
dev->name_assign_type = NET_NAME_RENAMED;
|
||||
@@ -20,7 +20,7 @@ DEFAULT_PACKAGES += kmod-qca-nss-dp kmod-qca-ssdk swconfig \
|
||||
kmod-usb-phy-ipq807x kmod-usb-dwc3-qcom-internal \
|
||||
kmod-ath11k-ahb ath11k-firmware-ipq60xx \
|
||||
kmod-gpio-button-hotplug iwinfo \
|
||||
qca-ssdk-shell kmod-qca-nss-drv-bridge-mgr \
|
||||
qca-ssdk-shell \
|
||||
uboot-envtools
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From: Andy Ren <andy.ren@getcruise.com>
|
||||
Date: Mon, 7 Nov 2022 09:42:42 -0800
|
||||
Subject: [PATCH] net/core: Allow live renaming when an interface is up
|
||||
|
||||
Allow a network interface to be renamed when the interface
|
||||
is up.
|
||||
|
||||
As described in the netconsole documentation [1], when netconsole is
|
||||
used as a built-in, it will bring up the specified interface as soon as
|
||||
possible. As a result, user space will not be able to rename the
|
||||
interface since the kernel disallows renaming of interfaces that are
|
||||
administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set
|
||||
by the kernel.
|
||||
|
||||
The original solution [2] to this problem was to add a new parameter to
|
||||
the netconsole configuration parameters that allows renaming of
|
||||
the interface used by netconsole while it is administratively up.
|
||||
However, during the discussion that followed, it became apparent that we
|
||||
have no reason to keep the current restriction and instead we should
|
||||
allow user space to rename interfaces regardless of their administrative
|
||||
state:
|
||||
|
||||
1. The restriction was put in place over 20 years ago when renaming was
|
||||
only possible via IOCTL and before rtnetlink started notifying user
|
||||
space about such changes like it does today.
|
||||
|
||||
2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version
|
||||
5.2 and no regressions were reported.
|
||||
|
||||
3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about
|
||||
the administrative state of interface.
|
||||
|
||||
Therefore, allow user space to rename running interfaces by removing the
|
||||
restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in
|
||||
possible triage by emitting a message to the kernel log that an
|
||||
interface was renamed while UP.
|
||||
|
||||
[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst
|
||||
[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/
|
||||
|
||||
Signed-off-by: Andy Ren <andy.ren@getcruise.com>
|
||||
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||||
Reviewed-by: David Ahern <dsahern@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
===================================================================
|
||||
--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/core/dev.c
|
||||
+++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
@@ -1125,7 +1125,8 @@ int dev_change_name(struct net_device *d
|
||||
}
|
||||
|
||||
if (oldname[0] && !strchr(oldname, '%'))
|
||||
- netdev_info(dev, "renamed from %s\n", oldname);
|
||||
+ netdev_info(dev, "renamed from %s%s\n", oldname,
|
||||
+ dev->flags & IFF_UP ? " (while UP)" : "");
|
||||
|
||||
old_assign_type = dev->name_assign_type;
|
||||
dev->name_assign_type = NET_NAME_RENAMED;
|
||||
@@ -20,7 +20,7 @@ DEFAULT_PACKAGES += kmod-qca-nss-dp kmod-qca-ssdk swconfig \
|
||||
kmod-usb-phy-ipq807x kmod-usb-dwc3-qcom-internal \
|
||||
kmod-ath11k-ahb ath11k-firmware-ipq807x \
|
||||
kmod-gpio-button-hotplug iwinfo \
|
||||
qca-ssdk-shell kmod-qca-nss-drv-bridge-mgr \
|
||||
qca-ssdk-shell \
|
||||
uboot-envtools
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
From: Andy Ren <andy.ren@getcruise.com>
|
||||
Date: Mon, 7 Nov 2022 09:42:42 -0800
|
||||
Subject: [PATCH] net/core: Allow live renaming when an interface is up
|
||||
|
||||
Allow a network interface to be renamed when the interface
|
||||
is up.
|
||||
|
||||
As described in the netconsole documentation [1], when netconsole is
|
||||
used as a built-in, it will bring up the specified interface as soon as
|
||||
possible. As a result, user space will not be able to rename the
|
||||
interface since the kernel disallows renaming of interfaces that are
|
||||
administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set
|
||||
by the kernel.
|
||||
|
||||
The original solution [2] to this problem was to add a new parameter to
|
||||
the netconsole configuration parameters that allows renaming of
|
||||
the interface used by netconsole while it is administratively up.
|
||||
However, during the discussion that followed, it became apparent that we
|
||||
have no reason to keep the current restriction and instead we should
|
||||
allow user space to rename interfaces regardless of their administrative
|
||||
state:
|
||||
|
||||
1. The restriction was put in place over 20 years ago when renaming was
|
||||
only possible via IOCTL and before rtnetlink started notifying user
|
||||
space about such changes like it does today.
|
||||
|
||||
2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version
|
||||
5.2 and no regressions were reported.
|
||||
|
||||
3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about
|
||||
the administrative state of interface.
|
||||
|
||||
Therefore, allow user space to rename running interfaces by removing the
|
||||
restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in
|
||||
possible triage by emitting a message to the kernel log that an
|
||||
interface was renamed while UP.
|
||||
|
||||
[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst
|
||||
[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/
|
||||
|
||||
Signed-off-by: Andy Ren <andy.ren@getcruise.com>
|
||||
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||||
Reviewed-by: David Ahern <dsahern@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -1152,8 +1152,6 @@ int dev_change_name(struct net_device *d
|
||||
BUG_ON(!dev_net(dev));
|
||||
|
||||
net = dev_net(dev);
|
||||
- if (dev->flags & IFF_UP)
|
||||
- return -EBUSY;
|
||||
|
||||
write_seqcount_begin(&devnet_rename_seq);
|
||||
|
||||
@@ -1171,7 +1169,8 @@ int dev_change_name(struct net_device *d
|
||||
}
|
||||
|
||||
if (oldname[0] && !strchr(oldname, '%'))
|
||||
- netdev_info(dev, "renamed from %s\n", oldname);
|
||||
+ netdev_info(dev, "renamed from %s%s\n", oldname,
|
||||
+ dev->flags & IFF_UP ? " (while UP)" : "");
|
||||
|
||||
old_assign_type = dev->name_assign_type;
|
||||
dev->name_assign_type = NET_NAME_RENAMED;
|
||||
@@ -0,0 +1,60 @@
|
||||
From: Andy Ren <andy.ren@getcruise.com>
|
||||
Date: Mon, 7 Nov 2022 09:42:42 -0800
|
||||
Subject: [PATCH] net/core: Allow live renaming when an interface is up
|
||||
|
||||
Allow a network interface to be renamed when the interface
|
||||
is up.
|
||||
|
||||
As described in the netconsole documentation [1], when netconsole is
|
||||
used as a built-in, it will bring up the specified interface as soon as
|
||||
possible. As a result, user space will not be able to rename the
|
||||
interface since the kernel disallows renaming of interfaces that are
|
||||
administratively up unless the 'IFF_LIVE_RENAME_OK' private flag was set
|
||||
by the kernel.
|
||||
|
||||
The original solution [2] to this problem was to add a new parameter to
|
||||
the netconsole configuration parameters that allows renaming of
|
||||
the interface used by netconsole while it is administratively up.
|
||||
However, during the discussion that followed, it became apparent that we
|
||||
have no reason to keep the current restriction and instead we should
|
||||
allow user space to rename interfaces regardless of their administrative
|
||||
state:
|
||||
|
||||
1. The restriction was put in place over 20 years ago when renaming was
|
||||
only possible via IOCTL and before rtnetlink started notifying user
|
||||
space about such changes like it does today.
|
||||
|
||||
2. The 'IFF_LIVE_RENAME_OK' flag was added over 3 years ago in version
|
||||
5.2 and no regressions were reported.
|
||||
|
||||
3. In-kernel listeners to 'NETDEV_CHANGENAME' do not seem to care about
|
||||
the administrative state of interface.
|
||||
|
||||
Therefore, allow user space to rename running interfaces by removing the
|
||||
restriction and the associated 'IFF_LIVE_RENAME_OK' flag. Help in
|
||||
possible triage by emitting a message to the kernel log that an
|
||||
interface was renamed while UP.
|
||||
|
||||
[1] https://www.kernel.org/doc/Documentation/networking/netconsole.rst
|
||||
[2] https://lore.kernel.org/netdev/20221102002420.2613004-1-andy.ren@getcruise.com/
|
||||
|
||||
Signed-off-by: Andy Ren <andy.ren@getcruise.com>
|
||||
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
|
||||
Reviewed-by: David Ahern <dsahern@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
Index: linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
===================================================================
|
||||
--- linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d.orig/net/core/dev.c
|
||||
+++ linux-5.4.164-qsdk-26349818b464f8c7b52d59ce73579d9f3dd6bd5d/net/core/dev.c
|
||||
@@ -1125,7 +1125,8 @@ int dev_change_name(struct net_device *d
|
||||
}
|
||||
|
||||
if (oldname[0] && !strchr(oldname, '%'))
|
||||
- netdev_info(dev, "renamed from %s\n", oldname);
|
||||
+ netdev_info(dev, "renamed from %s%s\n", oldname,
|
||||
+ dev->flags & IFF_UP ? " (while UP)" : "");
|
||||
|
||||
old_assign_type = dev->name_assign_type;
|
||||
dev->name_assign_type = NET_NAME_RENAMED;
|
||||
@@ -488,6 +488,7 @@ ${channel:+channel=$channel}
|
||||
${channel_list:+chanlist=$channel_list}
|
||||
${hostapd_noscan:+noscan=1}
|
||||
${tx_burst:+tx_queue_data2_burst=$tx_burst}
|
||||
#num_global_macaddr=$num_global_macaddr
|
||||
$base_cfg
|
||||
|
||||
EOF
|
||||
@@ -528,6 +529,7 @@ mac80211_hostapd_setup_bss() {
|
||||
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
|
||||
@@ -542,57 +544,9 @@ mac80211_get_addr() {
|
||||
|
||||
mac80211_generate_mac() {
|
||||
local phy="$1"
|
||||
local multiple_bssid="$2"
|
||||
local id="${macidx:-0}"
|
||||
|
||||
local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
|
||||
local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
|
||||
|
||||
[ "$mask" = "00:00:00:00:00:00" -a "$multiple_bssid" != 1 ] && {
|
||||
mask="ff:ff:ff:ff:ff:ff";
|
||||
|
||||
[ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt $id ] && {
|
||||
addr="$(mac80211_get_addr "$phy" "$id")"
|
||||
[ -n "$addr" ] && {
|
||||
echo "$addr"
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
|
||||
|
||||
local mask1=$1
|
||||
local mask6=$6
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
|
||||
[ "$multiple_bssid" -eq 1 ] && {
|
||||
printf "02:%s:%s:%s:%s:%02x" $b1 $2 $3 $4 $5 $macidx
|
||||
return
|
||||
}
|
||||
macidx=$(($id + 1))
|
||||
|
||||
local use_global=0
|
||||
[ "$id" -gt 0 -a "$macidx" -le "$num_global_macaddr" ] && use_global=1
|
||||
|
||||
[ "$((0x$mask1))" -gt 0 -a "$use_global" -lt 1 ] && {
|
||||
b1="0x$1"
|
||||
[ "$id" -gt 0 ] && \
|
||||
b1=$(($b1 ^ ((($id - !($b1 & 2)) << 2)) | 0x2))
|
||||
printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
|
||||
return
|
||||
}
|
||||
|
||||
[ "$((0x$mask6))" -lt 255 -a "$use_global" -gt 0 ] && {
|
||||
printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
|
||||
return
|
||||
}
|
||||
|
||||
off2=$(( (0x$6 + $id) / 0x100 ))
|
||||
printf "%s:%s:%s:%s:%02x:%02x" \
|
||||
$1 $2 $3 $4 \
|
||||
$(( (0x$5 + $off2) % 0x100 )) \
|
||||
$(( (0x$6 + $id) % 0x100 ))
|
||||
wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=$multiple_bssid
|
||||
}
|
||||
|
||||
find_phy() {
|
||||
@@ -626,11 +580,14 @@ mac80211_prepare_vif() {
|
||||
set_default powersave 0
|
||||
json_add_string _ifname "$ifname"
|
||||
|
||||
default_macaddr=
|
||||
[ -n "$macaddr" ] || {
|
||||
macaddr="$(mac80211_generate_mac $phy $multiple_bssid)"
|
||||
macaddr="$(mac80211_generate_mac $phy)"
|
||||
macidx="$(($macidx + 1))"
|
||||
default_macaddr=1
|
||||
}
|
||||
json_add_string _macaddr "$macaddr"
|
||||
json_add_string _default_macaddr "$default_macaddr"
|
||||
json_select ..
|
||||
|
||||
|
||||
@@ -754,7 +711,7 @@ mac80211_setup_adhoc() {
|
||||
|
||||
json_add_object "$ifname"
|
||||
json_add_string mode adhoc
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
json_add_string ssid "$ssid"
|
||||
json_add_string freq "$freq"
|
||||
json_add_string htmode "$iw_htmode"
|
||||
@@ -780,7 +737,7 @@ mac80211_setup_mesh() {
|
||||
|
||||
json_add_object "$ifname"
|
||||
json_add_string mode mesh
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
json_add_string ssid "$ssid"
|
||||
json_add_string freq "$freq"
|
||||
json_add_string htmode "$iw_htmode"
|
||||
@@ -831,7 +788,6 @@ wpa_supplicant_init_config() {
|
||||
wpa_supplicant_add_interface() {
|
||||
local ifname="$1"
|
||||
local mode="$2"
|
||||
local hostapd_ctrl="$3"
|
||||
local prev
|
||||
|
||||
_wpa_supplicant_common "$ifname"
|
||||
@@ -843,9 +799,8 @@ wpa_supplicant_add_interface() {
|
||||
json_add_string iface "$ifname"
|
||||
json_add_string mode "$mode"
|
||||
json_add_string config "$_config"
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
[ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
|
||||
[ -n "$hostapd_ctrl" ] && json_add_string hostapd_ctrl "$hostapd_ctrl"
|
||||
[ -n "$wds" ] && json_add_boolean 4addr "$wds"
|
||||
json_add_boolean powersave "$powersave"
|
||||
[ "$mode" = "mesh" ] && mac80211_add_mesh_params
|
||||
@@ -920,7 +875,7 @@ mac80211_setup_supplicant() {
|
||||
wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
|
||||
fi
|
||||
|
||||
wpa_supplicant_add_interface "$ifname" "$mode" "$hostapd_ctrl"
|
||||
wpa_supplicant_add_interface "$ifname" "$mode"
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -932,6 +887,7 @@ mac80211_setup_vif() {
|
||||
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
|
||||
@@ -1014,7 +970,7 @@ mac80211_reset_config() {
|
||||
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" '{}'
|
||||
wdev_tool "$phy" set_config '{}'
|
||||
}
|
||||
|
||||
drv_mac80211_setup() {
|
||||
@@ -1116,7 +1072,7 @@ drv_mac80211_setup() {
|
||||
|
||||
mac80211_prepare_iw_htmode
|
||||
active_ifnames=
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif ${multiple_bssid}
|
||||
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"
|
||||
@@ -1125,7 +1081,7 @@ drv_mac80211_setup() {
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
|
||||
|
||||
json_set_namespace wdev_uc prev
|
||||
wdev_tool "$phy" "$(json_dump)" $active_ifnames
|
||||
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
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 13:17:16 +0200
|
||||
Subject: [PATCH] cfg80211: allow grace period for DFS available after beacon
|
||||
shutdown
|
||||
|
||||
Fixes reconfiguring an AP on a DFS channel in non-ETSI regdomain
|
||||
|
||||
Fixes: b35a51c7dd25 ("cfg80211: Make pre-CAC results valid only for ETSI domain")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -162,6 +162,8 @@ enum ieee80211_channel_flags {
|
||||
* @dfs_state: current state of this channel. Only relevant if radar is required
|
||||
* on this channel.
|
||||
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
|
||||
+ * @dfs_state_last_available: timestamp (jiffies) of the last time when the
|
||||
+ * channel was available.
|
||||
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
|
||||
*/
|
||||
struct ieee80211_channel {
|
||||
@@ -178,6 +180,7 @@ struct ieee80211_channel {
|
||||
int orig_mag, orig_mpwr;
|
||||
enum nl80211_dfs_state dfs_state;
|
||||
unsigned long dfs_state_entered;
|
||||
+ unsigned long dfs_state_last_available;
|
||||
unsigned int dfs_cac_ms;
|
||||
};
|
||||
|
||||
--- a/net/wireless/ap.c
|
||||
+++ b/net/wireless/ap.c
|
||||
@@ -25,6 +25,8 @@ int __cfg80211_stop_ap(struct cfg80211_r
|
||||
if (!wdev->beacon_interval)
|
||||
return -ENOENT;
|
||||
|
||||
+ cfg80211_update_last_available(wdev->wiphy, &wdev->chandef);
|
||||
+
|
||||
err = rdev_stop_ap(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->conn_owner_nlportid = 0;
|
||||
@@ -35,9 +37,6 @@ int __cfg80211_stop_ap(struct cfg80211_r
|
||||
if (notify)
|
||||
nl80211_send_ap_stopped(wdev);
|
||||
|
||||
- /* Should we apply the grace period during beaconing interface
|
||||
- * shutdown also?
|
||||
- */
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
}
|
||||
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -411,6 +411,8 @@ static void cfg80211_set_chans_dfs_state
|
||||
|
||||
c->dfs_state = dfs_state;
|
||||
c->dfs_state_entered = jiffies;
|
||||
+ if (dfs_state == NL80211_DFS_AVAILABLE)
|
||||
+ c->dfs_state_last_available = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,6 +771,49 @@ static bool cfg80211_get_chans_dfs_avail
|
||||
return true;
|
||||
}
|
||||
|
||||
+static void
|
||||
+__cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ u32 center_freq,
|
||||
+ u32 bandwidth)
|
||||
+{
|
||||
+ struct ieee80211_channel *c;
|
||||
+ u32 freq, start_freq, end_freq;
|
||||
+
|
||||
+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||
+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||
+
|
||||
+ /*
|
||||
+ * Check entire range of channels for the bandwidth.
|
||||
+ * If any channel in between is disabled or has not
|
||||
+ * had gone through CAC return false
|
||||
+ */
|
||||
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||
+ c = ieee80211_get_channel_khz(wiphy, freq);
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+
|
||||
+ c->dfs_state_last_available = jiffies;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef)
|
||||
+{
|
||||
+ int width;
|
||||
+
|
||||
+ width = cfg80211_chandef_get_width(chandef);
|
||||
+ if (width < 0)
|
||||
+ return;
|
||||
+
|
||||
+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1),
|
||||
+ width);
|
||||
+ if (chandef->width != NL80211_CHAN_WIDTH_80P80)
|
||||
+ return;
|
||||
+
|
||||
+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2),
|
||||
+ width);
|
||||
+}
|
||||
+
|
||||
static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -483,6 +483,8 @@ void cfg80211_set_dfs_state(struct wiphy
|
||||
enum nl80211_dfs_state dfs_state);
|
||||
|
||||
void cfg80211_dfs_channels_update_work(struct work_struct *work);
|
||||
+void cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef);
|
||||
|
||||
unsigned int
|
||||
cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -858,6 +858,8 @@ void cfg80211_dfs_channels_update_work(s
|
||||
if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
|
||||
time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
|
||||
radar_event = NL80211_RADAR_NOP_FINISHED;
|
||||
+ timeout = c->dfs_state_entered +
|
||||
+ msecs_to_jiffies(time_dfs_update);
|
||||
} else {
|
||||
if (regulatory_pre_cac_allowed(wiphy) ||
|
||||
cfg80211_any_wiphy_oper_chan(wiphy, c))
|
||||
@@ -865,11 +867,10 @@ void cfg80211_dfs_channels_update_work(s
|
||||
|
||||
time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
|
||||
radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
|
||||
+ timeout = c->dfs_state_last_available +
|
||||
+ msecs_to_jiffies(time_dfs_update);
|
||||
}
|
||||
|
||||
- timeout = c->dfs_state_entered +
|
||||
- msecs_to_jiffies(time_dfs_update);
|
||||
-
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
c->dfs_state = NL80211_DFS_USABLE;
|
||||
c->dfs_state_entered = jiffies;
|
||||
@@ -771,10 +771,10 @@ hostapd_set_bss_options() {
|
||||
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.
|
||||
vlan_possible=1
|
||||
wps_not_configured=1
|
||||
[ "$macfilter" = radius ] && {
|
||||
append_radius_server
|
||||
vlan_possible=1
|
||||
}
|
||||
;;
|
||||
psk|sae|psk-sae)
|
||||
|
||||
@@ -34,7 +34,7 @@ boot() {
|
||||
case "$(board_name)" in
|
||||
cig,wf660a)
|
||||
mmc_dev=$(echo $(find_mmc_part "0:ETHPHYFW") | sed 's/^.\{5\}//')
|
||||
[ -n $mmc_dev ] && mount -t ext4 /dev/$mmc_dev /certificates
|
||||
[ -n "$mmc_dev" ] && mount -t ext4 /dev/$mmc_dev /certificates
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -75,7 +75,10 @@ boot() {
|
||||
PART_NAME=rootfs_1
|
||||
fi
|
||||
;;
|
||||
yuncore,ax840)
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
yuncore,ax840|\
|
||||
yuncore,fap655)
|
||||
PART_NAME=rootfs_1
|
||||
;;
|
||||
*)
|
||||
|
||||
@@ -4,10 +4,10 @@ PKG_NAME:=ucentral-client
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-client.git
|
||||
PKG_MIRROR_HASH:=208bc53ea0194a59ff4dc78c32033a393017b0b883aa4d7741595b61ad3a4fd3
|
||||
PKG_MIRROR_HASH:=49d19d1cddb538f233a7c1d588b5c765929a8fe28a1524d0455c4b516dcd0310
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-06-22
|
||||
PKG_SOURCE_VERSION:=d898a7afb595d6c2350d38d027bf142e72060662
|
||||
PKG_SOURCE_VERSION:=3bbcd36c6111e08df6c8f13e0079826ec417cc85
|
||||
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
@@ -231,14 +231,27 @@ function dhcp_subscriber_remove_cb(remove) {
|
||||
printf('dhcp remove: %.J\n', remove);
|
||||
}
|
||||
|
||||
function match_dhcp_relay_option82(format, hapd) {
|
||||
switch(format) {
|
||||
case 'ap-mac':
|
||||
uci.load('ucentral');
|
||||
let ucentral = uci.get_all('ucentral', 'config');
|
||||
return ucentral.serial;
|
||||
case 'ssid':
|
||||
return hapd.config.ssid;
|
||||
case 'vlan-id':
|
||||
return hapd.config.vlan_id;
|
||||
}
|
||||
}
|
||||
|
||||
function dhcp_relay_subscriber_notify_cb(notify) {
|
||||
let ifname = split(notify.data.info.device, '-v');
|
||||
let hapd = hostapd[ifname[0]];
|
||||
let vlan = ifname[1];
|
||||
if (hapd) {
|
||||
vlan ??= hapd.config.vlan_id;
|
||||
let circuit_id = `${vlan}`;
|
||||
let remote_id = hapd.bssid;
|
||||
let circuit_id = match_dhcp_relay_option82(relay['vlan' + vlan]?.circuit_id, hapd);
|
||||
let remote_id = match_dhcp_relay_option82(relay['vlan' + vlan]?.remote_id, hapd);
|
||||
return {
|
||||
address: relay['vlan' + vlan]?.server,
|
||||
options: [
|
||||
|
||||
@@ -4,10 +4,10 @@ PKG_NAME:=ucentral-schema
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL=https://github.com/Telecominfraproject/wlan-ucentral-schema.git
|
||||
PKG_MIRROR_HASH:=6da4c8a82c5393d54bfe1a91479730cc126e7de1cf1565a0274d600759e668e0
|
||||
PKG_MIRROR_HASH:=62571bb529e8b350bafdc63db3d7e02effa3edf5e5f19bfe8ced96c7cfb08b0e
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2022-05-29
|
||||
PKG_SOURCE_VERSION:=708b1de986b63c35e4f5e79a3183ffb4a36f40a1
|
||||
PKG_SOURCE_VERSION:=e99eaf9bdbbe68639b4632d7fec171d89c379dc5
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=BSD-3-Clause
|
||||
|
||||
@@ -8,6 +8,7 @@ board=$(board_name)
|
||||
|
||||
case "$board" in
|
||||
cig,wf186w|\
|
||||
cig,wf186h|\
|
||||
cig,wf194c4|\
|
||||
cig,wf194c|\
|
||||
cig,wf610d|\
|
||||
|
||||
10
feeds/ucentral/ucentral-schema/files/etc/uci-defaults/99-ucentral-event
Normal file → Executable file
10
feeds/ucentral/ucentral-schema/files/etc/uci-defaults/99-ucentral-event
Normal file → Executable file
@@ -1,5 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
case "$(board_name)" in
|
||||
"cig,wf186w")
|
||||
uci del event.config.wan_port
|
||||
uci add_list event.config.wan_port=eth0
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
wan=$(cat /etc/board.json | jsonfilter -e '@.network.wan.device')
|
||||
[ -z "$wan" ] && eval $(jsonfilter -i /etc/board.json -e 'wan=@.network.wan.ports.*')
|
||||
for w in $wan; do
|
||||
|
||||
@@ -68,7 +68,7 @@ global.start = function() {
|
||||
global.uci = require('uci').cursor();
|
||||
global.ubus.conn = require('ubus').connect();
|
||||
|
||||
for (let module in [ 'config', 'event', 'phy', 'local', 'station', 'command', 'policy' ]) {
|
||||
for (let module in [ 'config', 'event', 'phy', 'neighbor', 'local', 'station', 'command', 'policy' ]) {
|
||||
printf('loading ' + module + '\n');
|
||||
global[module] = require(module);
|
||||
if (exists(global[module], 'init'))
|
||||
|
||||
@@ -1,64 +1,75 @@
|
||||
function result(error, text, data) {
|
||||
function result(error, event, text, data) {
|
||||
let res = {
|
||||
error: error,
|
||||
text: text || 'unknown',
|
||||
...(data ? { data } : {}),
|
||||
...(data ? data : {}),
|
||||
};
|
||||
if (event)
|
||||
global.event.send('rrm.bss.command', res);
|
||||
return res;
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// ubus call usteer2 command '{"action": "kick", "addr": "1c:57:dc:37:3c:b1", "params": {"reason": 5, "ban_time": 30}}'
|
||||
// ubus call usteer2 command '{"action": "kick", "addr": "1c:57:dc:37:3c:b1", "reason": 5, "ban_time": 30 }'
|
||||
kick: function(msg) {
|
||||
if (global.station.kick(msg))
|
||||
return result(1, 'station ' + msg.mac + ' is unknown');
|
||||
if (!global.station.kick(msg))
|
||||
return result(1, msg.event, 'station ' + msg.addr + ' is unknown', { action: 'kick', addr: msg.addr });
|
||||
|
||||
return result(0, 'station ' + msg.mac + ' was kicked');
|
||||
return result(0, 0, 'station ' + msg.addr + ' was kicked', { action: 'kick', addr: msg.addr });
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "beacon_request", "addr": "4e:7f:3e:2c:8a:68", "params": {"channel": 36}}'
|
||||
// ubus call usteer2 command '{"action": "beacon_request", "addr": "4e:7f:3e:2c:8a:68", "params": {"ssid": "Cockney"}}'
|
||||
// ubus call usteer2 command '{"action": "beacon_request", "addr": "4e:7f:3e:2c:8a:68", "params": "channel": 1}'
|
||||
// ubus call usteer2 command '{"action": "beacon_request", "addr": "4e:7f:3e:2c:8a:68", "params": "ssid": "Pluto" }'
|
||||
// ubus call usteer2 get_beacon_request '{"addr": "4e:7f:3e:2c:8a:68"}'
|
||||
beacon_request: function(msg) {
|
||||
if (!global.station.beacon_request(msg))
|
||||
return result(1, 'station ' + msg.addr + ' is unknown');
|
||||
return result(1, msg.event, 'station ' + msg.addr + ' is unknown', { action: 'beacon_request', addr: msg.addr });
|
||||
|
||||
return result(0, 'station ' + msg.addr + ' beacon-request sent');
|
||||
return result(0, 0, 'station ' + msg.addr + ' beacon-request sent', { action: 'beacon_request', addr: msg.addr });
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "channel_switch", "addr": "34:eF:b6:aF:48:b1", "params": {"channel": 4, "band": "2G"}}'
|
||||
// ubus call usteer2 command '{"action": "channel_switch", "bssid": "34:eF:b6:aF:48:b1", "channel": 4 }'
|
||||
channel_switch: function(msg) {
|
||||
if (!global.local.switch_chan(msg))
|
||||
return result(1, 'BSS ' + msg.bssid + ' failed to trigger channel switch');
|
||||
return result(1, msg.event, 'BSS ' + msg.bssid + ' failed to trigger channel switch', { action: 'channel_switch', bssid: msg.bssid });
|
||||
|
||||
return result(0, 'BSS ' + msg.bssid + ' triggered channel switch');
|
||||
return result(0, msg.event, 'BSS ' + msg.bssid + ' triggered channel switch', { action: 'channel_switch', bssid: msg.bssid });
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "tx_power", "phy": "platform/soc/c000000.wifi+1", "params": {"level": 20}}'
|
||||
// ubus call usteer2 command '{"action": "tx_power", "bssid": "34:eF:b6:aF:48:b1", "level": 20}'
|
||||
tx_power: function(msg) {
|
||||
if (!global.phy.txpower(msg))
|
||||
return result(1, 'PHY ' + msg,phy + ' failed to set TX power');
|
||||
|
||||
return result(0, 'PHY ' + msg.phy + ' changed TX power');
|
||||
return result(1, msg.event, 'BSS ' + msg.bssid + ' failed to set TX power', { action: 'tx_power', bssid: msg.bssid });
|
||||
|
||||
let level = global.local.txpower(msg.bssid) / 100;
|
||||
return result(0, msg.event, 'BSS ' + msg.bssid + ' changed TX power', { action: 'tx_power', bssid: msg.bssid, level });
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "bss_transition", "addr": "4e:7f:3e:2c:8a:68", "params": { "neighbors": ["34:ef:b6:af:48:b1"]}}'
|
||||
// ubus call usteer2 command '{"action": "bss_transition", "addr": "4e:7f:3e:2c:8a:68", "neighbors": ["34:ef:b6:af:48:b1"] }'
|
||||
bss_transition: function(msg) {
|
||||
if (!global.station.bss_transition(msg))
|
||||
return result(1, 'BSS transition ' + msg.addr + ' failed to trigger');
|
||||
return result(1, msg.event, 'BSS transition ' + msg.addr + ' failed to trigger', { action: 'bss_transition', addr: msg.addr });
|
||||
|
||||
return result(0, 'BSS transition ' + msg.addr + ' triggered');
|
||||
return result(0, 0, 'BSS transition ' + msg.addr + ' triggered');
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "neighbors", "neighbors": [ [ "00:11:22:33:44:55", "OpenWifi", "34efb6af48b1af4900005301070603010300" ], [ "aa:bb:cc:dd:ee:ff", "OpenWifi2", "34efb6af48b1af4900005301070603010300" ] ] }'
|
||||
neighbors: function(msg) {
|
||||
if (!global.neighbor.remote(msg))
|
||||
return result(1, msg.event, 'Failed to set neighbors', { action: 'neighbors' });
|
||||
return result(0, 0, 'applied neighbor reports');
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
handle: function(msg) {
|
||||
if (!actions[msg.action])
|
||||
return result(1, 'unknown action ' + msg.action);
|
||||
return result(1, msg.event, 'unknown action ' + msg.action);
|
||||
try {
|
||||
return actions[msg.action](msg);
|
||||
} catch(e) {
|
||||
return result(1, 'action ' + msg.action + ' failed to execute');
|
||||
printf('%.J\n', e.stacktrace[0].context);
|
||||
return result(1, msg.event, 'action ' + msg.action + ' failed to execute');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,7 +6,16 @@ let state = {};
|
||||
let hapd = {};
|
||||
let handlers = {};
|
||||
|
||||
function channel_to_freq(band, channel) {
|
||||
function channel_to_freq(cur_freq, channel) {
|
||||
|
||||
let band;
|
||||
if (cur_freq <= 2484)
|
||||
band = '2G';
|
||||
else if (cur_freq <= 5885)
|
||||
band = '5G';
|
||||
else
|
||||
band = '6G';
|
||||
|
||||
if (band == '2G' && channel >= 1 && channel <= 13)
|
||||
return 2407 + channel * 5;
|
||||
else if (band == '2G' && channel == 14)
|
||||
@@ -58,23 +67,6 @@ function hapd_update() {
|
||||
return 5000;
|
||||
}
|
||||
|
||||
function hapd_nr_set(iface) {
|
||||
let list = [];
|
||||
for (let k, v in hapd) {
|
||||
if (k == iface || v.ssid != hapd[iface].ssid)
|
||||
continue;
|
||||
push(list, v.rrm_nr);
|
||||
|
||||
global.ubus.conn.call('hostapd.' + iface, 'rrm_nr_set', { list });
|
||||
}
|
||||
}
|
||||
|
||||
function hapd_nr_update(ssid) {
|
||||
for (let k, v in hapd)
|
||||
if (v.ssid == ssid)
|
||||
hapd_nr_set(k);
|
||||
}
|
||||
|
||||
function hapd_subunsub(path, sub) {
|
||||
/* check if this is a hostapd instance */
|
||||
let name = split(path, '.');
|
||||
@@ -88,6 +80,7 @@ function hapd_subunsub(path, sub) {
|
||||
/* the hostapd instance disappeared */
|
||||
if (!sub) {
|
||||
global.event.send('rrm.bss.del', { bssid: hapd[name] });
|
||||
global.neighbor.local_del(name);
|
||||
delete hapd[name];
|
||||
delete state[name];
|
||||
return;
|
||||
@@ -122,14 +115,15 @@ function hapd_subunsub(path, sub) {
|
||||
|
||||
/* ask hostapd for the local neighbourhood report data */
|
||||
let rrm = global.ubus.conn.call(path, 'rrm_nr_get_own');
|
||||
if (rrm && rrm.value)
|
||||
if (rrm && rrm.value) {
|
||||
hapd[name].rrm_nr = rrm.value;
|
||||
global.neighbor.local_add(name, rrm.value);
|
||||
}
|
||||
|
||||
global.neighbor.update();
|
||||
|
||||
/* trigger an initial channel survey */
|
||||
channel_survey(name);
|
||||
|
||||
/* update the neighborhood reports */
|
||||
hapd_nr_update(hapd[name].ssid);
|
||||
//channel_survey(name);
|
||||
|
||||
/* send an event */
|
||||
global.event.send('rrm.bss.add', {
|
||||
@@ -137,7 +131,8 @@ function hapd_subunsub(path, sub) {
|
||||
ssid: hapd[name].ssid,
|
||||
freq: hapd[name].freq,
|
||||
channel: hapd[name].channel,
|
||||
op_class: hapd[name].op_class
|
||||
op_class: hapd[name].op_class,
|
||||
rrm_nr: hapd[name].rrm_nr,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,6 +164,10 @@ function ucentral_handle_event(req) {
|
||||
printf('%.J\n', req);
|
||||
}
|
||||
|
||||
function channel_switch_handler(type, data) {
|
||||
global.event.send('rrm.bss.channel-switch', { bssid: data.bssid, freq: data.freq });
|
||||
}
|
||||
|
||||
return {
|
||||
status: function() {
|
||||
return hapd;
|
||||
@@ -193,7 +192,8 @@ return {
|
||||
ucentral_subunsub(true);
|
||||
}
|
||||
|
||||
uloop_timeout(hapd_update, 5000);
|
||||
// uloop_timeout(hapd_update, 5000);
|
||||
global.local.register_handler('channel-switch', channel_switch_handler);
|
||||
},
|
||||
|
||||
register_handler: function(event, handler) {
|
||||
@@ -203,16 +203,36 @@ return {
|
||||
},
|
||||
|
||||
switch_chan: function(msg) {
|
||||
if (!msg.addr || !msg.params?.band || !msg.params?.channel)
|
||||
if (!msg.bssid || !msg.channel)
|
||||
return false;
|
||||
for (let bss, v in hapd) {
|
||||
if (v.bssid != lc(msg.addr))
|
||||
if (v.bssid != lc(msg.bssid))
|
||||
continue;
|
||||
return global.ubus.conn.call('hostapd.' + bss, 'switch_chan', {
|
||||
freq: channel_to_freq(msg.param.band, mag.param.channel),
|
||||
freq: channel_to_freq(v.freq, msg.channel),
|
||||
bcn_count: 10
|
||||
}) == null;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
bssid_to_phy: function(bssid) {
|
||||
for (let bss, v in hapd) {
|
||||
if (v.bssid != lc(bssid))
|
||||
continue;
|
||||
let iface = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_INTERFACE, 0, { dev: bss });
|
||||
return iface.wiphy;
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
txpower: function(bssid) {
|
||||
for (let bss, v in hapd) {
|
||||
if (v.bssid != lc(bssid))
|
||||
continue;
|
||||
let iface = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_INTERFACE, 0, { dev: bss });
|
||||
return iface.wiphy_tx_power_level;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
};
|
||||
|
||||
53
feeds/ucentral/usteer2/files/usr/share/usteer/neighbor.uc
Normal file
53
feeds/ucentral/usteer2/files/usr/share/usteer/neighbor.uc
Normal file
@@ -0,0 +1,53 @@
|
||||
let local = { };
|
||||
let remote = [ ];
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
},
|
||||
|
||||
local_add: function(dev, data) {
|
||||
local[dev] = data;
|
||||
},
|
||||
|
||||
local_del: function(dev) {
|
||||
delete local[dev];
|
||||
},
|
||||
|
||||
get: function(dev) {
|
||||
let result = [];
|
||||
|
||||
for (let k, v in remote) {
|
||||
if (local[dev][1] != v[1])
|
||||
continue;
|
||||
push(result, v);
|
||||
}
|
||||
for (let k, v in local) {
|
||||
if (k == dev || local[dev][1] != v[1])
|
||||
continue;
|
||||
push(result, v);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
update: function() {
|
||||
for (let dev in local) {
|
||||
let list = this.get(dev);
|
||||
global.ubus.conn.call('hostapd.' + dev, 'rrm_nr_set', { list });
|
||||
}
|
||||
},
|
||||
|
||||
remote: function(msg) {
|
||||
for (let neighbor in msg.neighbors) {
|
||||
if (type(neighbor) != 'array' || length(neighbor) != 3)
|
||||
return false;
|
||||
for (let i = 0; i < 3; i++)
|
||||
if (type(neighbor[i]) != 'string')
|
||||
return false;
|
||||
}
|
||||
remote = msg.neighbors;
|
||||
this.update();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -147,12 +147,12 @@ return {
|
||||
},
|
||||
|
||||
txpower: function(msg) {
|
||||
if (!msg.phy || !msg.params?.level)
|
||||
if (!msg.bssid || !msg.level)
|
||||
return false;
|
||||
if (!this.phys[msg.phy])
|
||||
return false;
|
||||
|
||||
global.nl80211.request(global.nl80211.const.NL80211_CMD_SET_WIPHY, 0, { wiphy: this.phys[msg.phy].index, wiphy_tx_power_setting: 2, wiphy_tx_power_level: msg.params.level * 100});
|
||||
let wiphy = global.local.bssid_to_phy(msg.bssid);
|
||||
if (wiphy < 0)
|
||||
return false;
|
||||
global.nl80211.request(global.nl80211.const.NL80211_CMD_SET_WIPHY, 0, { wiphy, wiphy_tx_power_setting: 2, wiphy_tx_power_level: msg.level * 100});
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -164,7 +164,7 @@ return {
|
||||
},
|
||||
|
||||
beacon_request: function(msg) {
|
||||
if (!msg.addr || (!msg.params?.channel && !msg.params?.ssid))
|
||||
if (!msg.addr || (!msg.channel && !msg.ssid))
|
||||
return false;
|
||||
|
||||
let station = stations[msg.addr];
|
||||
@@ -185,20 +185,20 @@ return {
|
||||
let payload = {
|
||||
addr: msg.addr,
|
||||
mode: msg.params?.mode || 1,
|
||||
op_class: msg.params?.op_class || 128,
|
||||
duration: msg.params?.duration || 100,
|
||||
op_class: msg.op_class || 128,
|
||||
duration: msg.duration || 100,
|
||||
};
|
||||
if (msg.params.channel)
|
||||
payload.channel = msg.params.channel;
|
||||
if (msg.channel)
|
||||
payload.channel = msg.channel;
|
||||
else
|
||||
payload.ssid = msg.params.ssid;
|
||||
payload.ssid = msg.ssid;
|
||||
global.ubus.conn.call(`hostapd.${station.device}`, 'rrm_beacon_req', payload);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
kick: function(msg) {
|
||||
if (!msg.addr || !msg.params?.ban_time || !msg.params?.reason)
|
||||
if (!msg.addr || !msg.ban_time || !msg.reason)
|
||||
return false;
|
||||
|
||||
if (!exists(stations, msg.addr))
|
||||
@@ -206,9 +206,9 @@ return {
|
||||
|
||||
let payload = {
|
||||
addr: msg.addr,
|
||||
reason: msg.params.reason,
|
||||
reason: msg.reason,
|
||||
deauth: 1,
|
||||
ban_time: msg.params.ban_time
|
||||
ban_time: msg.ban_time
|
||||
};
|
||||
|
||||
/* tell hostapd to kick a station via ubus */
|
||||
@@ -223,17 +223,16 @@ return {
|
||||
return stations;
|
||||
},
|
||||
|
||||
// ubus call usteer2 command '{"action": "bss_transition", "addr": "4e:7f:3e:2c:8a:68", "params": { "neighbors": ["36:ef:b6:af:48:b1"]}}'
|
||||
bss_transition: function(msg) {
|
||||
if (!msg.addr || !msg.params?.neighbors)
|
||||
if (!msg.addr || !msg.neighbors)
|
||||
return false;
|
||||
if (!stations[msg.addr])
|
||||
return false;
|
||||
|
||||
let neighbors = [];
|
||||
for (let i = 0; i < 5; i++)
|
||||
if (msg.params?.neighbors[i])
|
||||
push(neighbors, replace(msg.params?.neighbors[i], ':', ''));
|
||||
if (msg.neighbors[i])
|
||||
push(neighbors, replace(msg.neighbors[i], ':', ''));
|
||||
|
||||
let ret = global.ubus.conn.call(`hostapd.${stations[msg.addr].device}`, 'wnm_disassoc_imminent', {
|
||||
addr: msg.addr, duration: 20, abridged: 1, neighbors }) == null;
|
||||
|
||||
@@ -26,6 +26,7 @@ endef
|
||||
ALLWIFIBOARDS:= \
|
||||
cig-wf188 \
|
||||
cig-wf186w \
|
||||
cig-wf186h \
|
||||
cig-wf660a \
|
||||
cig-wf194c \
|
||||
cig-wf194c4 \
|
||||
@@ -348,6 +349,7 @@ endef
|
||||
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf188,Cigtech WF188))
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf186w,Cigtech WF186w))
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf186h,Cigtech WF186h))
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf660a,Cigtech WF660a))
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf194c,Cigtech WF194c))
|
||||
$(eval $(call generate-ath11k-wifi-package,cig-wf194c4,Cigtech WF194c4))
|
||||
|
||||
BIN
feeds/wifi-ax/ath11k-wifi/board-cig-wf186h.bin.IPQ5018
Executable file
BIN
feeds/wifi-ax/ath11k-wifi/board-cig-wf186h.bin.IPQ5018
Executable file
Binary file not shown.
BIN
feeds/wifi-ax/ath11k-wifi/board-cig-wf186h.bin.QCN6122
Executable file
BIN
feeds/wifi-ax/ath11k-wifi/board-cig-wf186h.bin.QCN6122
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
import * as nl80211 from "nl80211";
|
||||
import * as rtnl from "rtnl";
|
||||
import { readfile } from "fs";
|
||||
import { readfile, glob, basename, readlink } from "fs";
|
||||
|
||||
const iftypes = {
|
||||
ap: nl80211.const.NL80211_IFTYPE_AP,
|
||||
@@ -94,6 +94,156 @@ function wdev_create(phy, name, data)
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -150,7 +300,7 @@ function is_equal(val1, val2) {
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (!val1[key])
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
@@ -165,4 +315,4 @@ function vlist_new(cb) {
|
||||
}, vlist_proto);
|
||||
}
|
||||
|
||||
export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };
|
||||
export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac, phy_open };
|
||||
|
||||
@@ -725,8 +725,7 @@ hostapd_set_bss_options() {
|
||||
[ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N"
|
||||
}
|
||||
|
||||
set_default nasid "${macaddr//\:}"
|
||||
append bss_conf "nas_identifier=$nasid" "$N"
|
||||
[ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N"
|
||||
|
||||
[ -n "$acct_server" ] && {
|
||||
append bss_conf "acct_server_addr=$acct_server" "$N"
|
||||
@@ -772,6 +771,7 @@ hostapd_set_bss_options() {
|
||||
# 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
|
||||
vlan_possible=1
|
||||
[ "$macfilter" = radius ] && {
|
||||
append_radius_server
|
||||
vlan_possible=1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
let libubus = require("ubus");
|
||||
import { open, readfile } from "fs";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac } from "common";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common";
|
||||
|
||||
let ubus = libubus.connect();
|
||||
|
||||
@@ -31,7 +31,7 @@ function iface_remove(cfg)
|
||||
wdev_remove(bss.ifname);
|
||||
}
|
||||
|
||||
function iface_gen_config(phy, config)
|
||||
function iface_gen_config(phy, config, start_disabled)
|
||||
{
|
||||
let str = `data:
|
||||
${join("\n", config.radio.data)}
|
||||
@@ -41,18 +41,92 @@ channel=${config.radio.channel}
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
let type = i > 0 ? "bss" : "interface";
|
||||
let nasid = bss.nasid ?? replace(bss.bssid, ":", "");
|
||||
|
||||
str += `
|
||||
${type}=${bss.ifname}
|
||||
bssid=${bss.bssid}
|
||||
${join("\n", bss.data)}
|
||||
nas_identifier=${nasid}
|
||||
`;
|
||||
if (start_disabled)
|
||||
str += `
|
||||
start_disabled=1
|
||||
`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function iface_restart(phy, config, old_config)
|
||||
function iface_freq_info(iface, config, params)
|
||||
{
|
||||
let freq = params.frequency;
|
||||
if (!freq)
|
||||
return null;
|
||||
|
||||
let sec_offset = params.sec_chan_offset;
|
||||
if (sec_offset != -1 && sec_offset != 1)
|
||||
sec_offset = 0;
|
||||
|
||||
let width = 0;
|
||||
for (let line in config.radio.data) {
|
||||
if (!sec_offset && match(line, /^ht_capab=.*HT40/)) {
|
||||
sec_offset = null; // auto-detect
|
||||
continue;
|
||||
}
|
||||
|
||||
let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
val = int(val[2]);
|
||||
if (val > width)
|
||||
width = val;
|
||||
}
|
||||
|
||||
if (freq < 4000)
|
||||
width = 0;
|
||||
|
||||
return hostapd.freq_info(freq, sec_offset, width);
|
||||
}
|
||||
|
||||
function iface_add(phy, config, phy_status)
|
||||
{
|
||||
let config_inline = iface_gen_config(phy, config, !!phy_status);
|
||||
|
||||
let bss = config.bss[0];
|
||||
let ret = hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
if (!phy_status)
|
||||
return true;
|
||||
|
||||
let iface = hostapd.interfaces[bss.ifname];
|
||||
if (!iface)
|
||||
return false;
|
||||
|
||||
let freq_info = iface_freq_info(iface, config, phy_status);
|
||||
|
||||
return iface.start(freq_info) >= 0;
|
||||
}
|
||||
|
||||
function iface_config_macaddr_list(config)
|
||||
{
|
||||
let macaddr_list = {};
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
if (!bss.default_macaddr)
|
||||
macaddr_list[bss.bssid] = i;
|
||||
}
|
||||
|
||||
return macaddr_list;
|
||||
}
|
||||
|
||||
function iface_restart(phydev, config, old_config)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
iface_remove(old_config);
|
||||
iface_remove(config);
|
||||
|
||||
@@ -61,15 +135,29 @@ function iface_restart(phy, config, old_config)
|
||||
return;
|
||||
}
|
||||
|
||||
phydev.macaddr_init(iface_config_macaddr_list(config));
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let bss = config.bss[i];
|
||||
if (bss.default_macaddr)
|
||||
bss.bssid = phydev.macaddr_next();
|
||||
}
|
||||
|
||||
let bss = config.bss[0];
|
||||
let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
||||
if (err)
|
||||
hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
||||
let config_inline = iface_gen_config(phy, config);
|
||||
|
||||
let ubus = hostapd.data.ubus;
|
||||
let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy });
|
||||
if (phy_status && phy_status.state == "COMPLETED") {
|
||||
if (iface_add(phy, config, phy_status))
|
||||
return;
|
||||
|
||||
hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`);
|
||||
}
|
||||
|
||||
ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
|
||||
if (hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`) < 0)
|
||||
if (!iface_add(phy, config))
|
||||
hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
||||
ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
|
||||
}
|
||||
@@ -111,8 +199,65 @@ function bss_reload_psk(bss, config, old_config)
|
||||
hostapd.printf(`Reload WPA PSK file for bss ${config.ifname}: ${ret}`);
|
||||
}
|
||||
|
||||
function iface_reload_config(phy, config, old_config)
|
||||
function remove_file_fields(config)
|
||||
{
|
||||
return filter(config, (line) => !hostapd.data.file_fields[split(line, "=")[0]]);
|
||||
}
|
||||
|
||||
function bss_remove_file_fields(config)
|
||||
{
|
||||
let new_cfg = {};
|
||||
|
||||
for (let key in config)
|
||||
new_cfg[key] = config[key];
|
||||
new_cfg.data = remove_file_fields(new_cfg.data);
|
||||
new_cfg.hash = {};
|
||||
for (let key in config.hash)
|
||||
new_cfg.hash[key] = config.hash[key];
|
||||
delete new_cfg.hash.wpa_psk_file;
|
||||
delete new_cfg.hash.vlan_file;
|
||||
|
||||
return new_cfg;
|
||||
}
|
||||
|
||||
function bss_config_hash(config)
|
||||
{
|
||||
return hostapd.sha1(remove_file_fields(config) + "");
|
||||
}
|
||||
|
||||
function bss_find_existing(config, prev_config, prev_hash)
|
||||
{
|
||||
let hash = bss_config_hash(config.data);
|
||||
|
||||
for (let i = 0; i < length(prev_config.bss); i++) {
|
||||
if (!prev_hash[i] || hash != prev_hash[i])
|
||||
continue;
|
||||
|
||||
prev_hash[i] = null;
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function get_config_bss(config, idx)
|
||||
{
|
||||
if (!config.bss[idx]) {
|
||||
hostapd.printf(`Invalid bss index ${idx}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
let ifname = config.bss[idx].ifname;
|
||||
if (!ifname)
|
||||
hostapd.printf(`Could not find bss ${config.bss[idx].ifname}`);
|
||||
|
||||
return hostapd.bss[ifname];
|
||||
}
|
||||
|
||||
function iface_reload_config(phydev, config, old_config)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
if (!old_config || !is_equal(old_config.radio, config.radio))
|
||||
return false;
|
||||
|
||||
@@ -122,82 +267,230 @@ function iface_reload_config(phy, config, old_config)
|
||||
if (!old_config.bss || !old_config.bss[0])
|
||||
return false;
|
||||
|
||||
if (config.bss[0].ifname != old_config.bss[0].ifname)
|
||||
return false;
|
||||
|
||||
let iface_name = config.bss[0].ifname;
|
||||
let iface_name = old_config.bss[0].ifname;
|
||||
let iface = hostapd.interfaces[iface_name];
|
||||
if (!iface)
|
||||
if (!iface) {
|
||||
hostapd.printf(`Could not find previous interface ${iface_name}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let first_bss = hostapd.bss[iface_name];
|
||||
if (!first_bss)
|
||||
if (!first_bss) {
|
||||
hostapd.printf(`Could not find bss of previous interface ${iface_name}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let macaddr_list = iface_config_macaddr_list(config);
|
||||
let bss_list = [];
|
||||
let bss_list_cfg = [];
|
||||
let prev_bss_hash = [];
|
||||
|
||||
for (let bss in old_config.bss) {
|
||||
let hash = bss_config_hash(bss.data);
|
||||
push(prev_bss_hash, bss_config_hash(bss.data));
|
||||
}
|
||||
|
||||
// Step 1: find (possibly renamed) interfaces with the same config
|
||||
// and store them in the new order (with gaps)
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let prev;
|
||||
|
||||
// For fullmac devices, the first interface needs to be preserved,
|
||||
// since it's treated as the master
|
||||
if (!i && phy_is_fullmac(phy)) {
|
||||
prev = 0;
|
||||
prev_bss_hash[0] = null;
|
||||
} else {
|
||||
prev = bss_find_existing(config.bss[i], old_config, prev_bss_hash);
|
||||
}
|
||||
if (prev < 0)
|
||||
continue;
|
||||
|
||||
let cur_config = config.bss[i];
|
||||
let prev_config = old_config.bss[prev];
|
||||
|
||||
let prev_bss = get_config_bss(old_config, prev);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
// try to preserve MAC address of this BSS by reassigning another
|
||||
// BSS if necessary
|
||||
if (cur_config.default_macaddr &&
|
||||
!macaddr_list[prev_config.bssid]) {
|
||||
macaddr_list[prev_config.bssid] = i;
|
||||
cur_config.bssid = prev_config.bssid;
|
||||
}
|
||||
|
||||
bss_list[i] = prev_bss;
|
||||
bss_list_cfg[i] = old_config.bss[prev];
|
||||
}
|
||||
|
||||
if (config.mbssid && !bss_list_cfg[0]) {
|
||||
hostapd.printf("First BSS changed with MBSSID enabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: if none were found, rename and preserve the first one
|
||||
if (length(bss_list) == 0) {
|
||||
// can't change the bssid of the first bss
|
||||
if (config.bss[0].bssid != old_config.bss[0].bssid) {
|
||||
if (!config.bss[0].default_macaddr) {
|
||||
hostapd.printf(`BSSID of first interface changed: ${lc(old_config.bss[0].bssid)} -> ${lc(config.bss[0].bssid)}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
config.bss[0].bssid = old_config.bss[0].bssid;
|
||||
}
|
||||
|
||||
let prev_bss = get_config_bss(old_config, 0);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
macaddr_list[config.bss[0].bssid] = 0;
|
||||
bss_list[0] = prev_bss;
|
||||
bss_list_cfg[0] = old_config.bss[0];
|
||||
prev_bss_hash[0] = null;
|
||||
}
|
||||
|
||||
// Step 3: delete all unused old interfaces
|
||||
for (let i = 0; i < length(prev_bss_hash); i++) {
|
||||
if (!prev_bss_hash[i])
|
||||
continue;
|
||||
|
||||
let prev_bss = get_config_bss(old_config, i);
|
||||
if (!prev_bss)
|
||||
return false;
|
||||
|
||||
let ifname = old_config.bss[i].ifname;
|
||||
hostapd.printf(`Remove bss '${ifname}' on phy '${phy}'`);
|
||||
prev_bss.delete();
|
||||
wdev_remove(ifname);
|
||||
}
|
||||
|
||||
// Step 4: rename preserved interfaces, use temporary name on duplicates
|
||||
let rename_list = [];
|
||||
for (let i = 0; i < length(bss_list); i++) {
|
||||
if (!bss_list[i])
|
||||
continue;
|
||||
|
||||
let old_ifname = bss_list_cfg[i].ifname;
|
||||
let new_ifname = config.bss[i].ifname;
|
||||
if (old_ifname == new_ifname)
|
||||
continue;
|
||||
|
||||
if (hostapd.bss[new_ifname]) {
|
||||
new_ifname = "tmp_" + substr(hostapd.sha1(new_ifname), 0, 8);
|
||||
push(rename_list, i);
|
||||
}
|
||||
|
||||
hostapd.printf(`Rename bss ${old_ifname} to ${new_ifname}`);
|
||||
if (!bss_list[i].rename(new_ifname)) {
|
||||
hostapd.printf(`Failed to rename bss ${old_ifname} to ${new_ifname}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
bss_list_cfg[i].ifname = new_ifname;
|
||||
}
|
||||
|
||||
// Step 5: rename interfaces with temporary names
|
||||
for (let i in rename_list) {
|
||||
let new_ifname = config.bss[i].ifname;
|
||||
if (!bss_list[i].rename(new_ifname)) {
|
||||
hostapd.printf(`Failed to rename bss to ${new_ifname}`);
|
||||
return false;
|
||||
}
|
||||
bss_list_cfg[i].ifname = new_ifname;
|
||||
}
|
||||
|
||||
// Step 6: assign BSSID for newly created interfaces
|
||||
let macaddr_data = {
|
||||
num_global: config.num_global_macaddr ?? 1,
|
||||
mbssid: config.mbssid ?? 0,
|
||||
};
|
||||
macaddr_list = phydev.macaddr_init(macaddr_list, macaddr_data);
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
if (bss_list[i])
|
||||
continue;
|
||||
let bsscfg = config.bss[i];
|
||||
|
||||
let mac_idx = macaddr_list[bsscfg.bssid];
|
||||
if (mac_idx < 0)
|
||||
macaddr_list[bsscfg.bssid] = i;
|
||||
if (mac_idx == i)
|
||||
continue;
|
||||
|
||||
// statically assigned bssid of the new interface is in conflict
|
||||
// with the bssid of a reused interface. reassign the reused interface
|
||||
if (!bsscfg.default_macaddr) {
|
||||
// can't update bssid of the first BSS, need to restart
|
||||
if (!mac_idx < 0)
|
||||
return false;
|
||||
|
||||
bsscfg = config.bss[mac_idx];
|
||||
}
|
||||
|
||||
let addr = phydev.macaddr_next(i);
|
||||
if (!addr) {
|
||||
hostapd.printf(`Failed to generate mac address for phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
bsscfg.bssid = addr;
|
||||
}
|
||||
|
||||
let config_inline = iface_gen_config(phy, config);
|
||||
|
||||
bss_reload_psk(first_bss, config.bss[0], old_config.bss[0]);
|
||||
if (!is_equal(config.bss[0], old_config.bss[0])) {
|
||||
if (phy_is_fullmac(phy))
|
||||
return false;
|
||||
// Step 7: fill in the gaps with new interfaces
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
let ifname = config.bss[i].ifname;
|
||||
let bss = bss_list[i];
|
||||
|
||||
if (config.bss[0].bssid != old_config.bss[0].bssid)
|
||||
if (bss)
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Add bss ${ifname} on phy ${phy}`);
|
||||
bss_list[i] = iface.add_bss(config_inline, i);
|
||||
if (!bss_list[i]) {
|
||||
hostapd.printf(`Failed to add new bss ${ifname} on phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: update interface bss order
|
||||
if (!iface.set_bss_order(bss_list)) {
|
||||
hostapd.printf(`Failed to update BSS order on phy '${phy}'`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 9: update config
|
||||
for (let i = 0; i < length(config.bss); i++) {
|
||||
if (!bss_list_cfg[i])
|
||||
continue;
|
||||
|
||||
let ifname = config.bss[i].ifname;
|
||||
let bss = bss_list[i];
|
||||
|
||||
if (is_equal(config.bss[i], bss_list_cfg[i]))
|
||||
continue;
|
||||
|
||||
if (is_equal(bss_remove_file_fields(config.bss[i]),
|
||||
bss_remove_file_fields(bss_list_cfg[i]))) {
|
||||
hostapd.printf(`Update config data files for bss ${ifname}`);
|
||||
if (bss.set_config(config_inline, i, true) < 0) {
|
||||
hostapd.printf(`Could not update config data files for bss ${ifname}`);
|
||||
return false;
|
||||
} else {
|
||||
bss.ctrl("RELOAD_WPA_PSK");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bss_reload_psk(bss, config.bss[i], bss_list_cfg[i]);
|
||||
if (is_equal(config.bss[i], bss_list_cfg[i]))
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
|
||||
if (first_bss.set_config(config_inline, 0) < 0) {
|
||||
hostapd.printf(`Failed to set config`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let new_cfg = array_to_obj(config.bss, "ifname", 1);
|
||||
let old_cfg = array_to_obj(old_config.bss, "ifname", 1);
|
||||
|
||||
for (let name in old_cfg) {
|
||||
let bss = hostapd.bss[name];
|
||||
if (!bss) {
|
||||
hostapd.printf(`bss '${name}' not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new_cfg[name]) {
|
||||
hostapd.printf(`Remove bss '${name}' on phy '${phy}'`);
|
||||
bss.delete();
|
||||
wdev_remove(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
let new_cfg_data = new_cfg[name];
|
||||
delete new_cfg[name];
|
||||
|
||||
if (is_equal(old_cfg[name], new_cfg_data))
|
||||
continue;
|
||||
|
||||
hostapd.printf(`Reload config for bss '${name}' on phy '${phy}'`);
|
||||
let idx = find_array_idx(config.bss, "ifname", name);
|
||||
if (idx < 0) {
|
||||
hostapd.printf(`bss index not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bss.set_config(config_inline, idx) < 0) {
|
||||
hostapd.printf(`Failed to set config`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (let name in new_cfg) {
|
||||
hostapd.printf(`Add bss '${name}' on phy '${phy}'`);
|
||||
|
||||
let idx = find_array_idx(config.bss, "ifname", name);
|
||||
if (idx < 0) {
|
||||
hostapd.printf(`bss index not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iface.add_bss(config_inline, idx) < 0) {
|
||||
hostapd.printf(`Failed to add bss`);
|
||||
if (bss.set_config(config_inline, i) < 0) {
|
||||
hostapd.printf(`Failed to set config for bss ${ifname}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,6 +498,14 @@ function iface_reload_config(phy, config, old_config)
|
||||
return true;
|
||||
}
|
||||
|
||||
function iface_update_supplicant_macaddr(phy, config)
|
||||
{
|
||||
let macaddr_list = [];
|
||||
for (let i = 0; i < length(config.bss); i++)
|
||||
push(macaddr_list, config.bss[i].bssid);
|
||||
ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
|
||||
}
|
||||
|
||||
function iface_set_config(phy, config)
|
||||
{
|
||||
let old_config = hostapd.data.config[phy];
|
||||
@@ -214,14 +515,28 @@ function iface_set_config(phy, config)
|
||||
if (!config)
|
||||
return iface_remove(old_config);
|
||||
|
||||
let ret = iface_reload_config(phy, config, old_config);
|
||||
if (ret) {
|
||||
hostapd.printf(`Reloaded settings for phy ${phy}`);
|
||||
return 0;
|
||||
let phydev = phy_open(phy);
|
||||
if (!phydev) {
|
||||
hostapd.printf(`Failed to open phy ${phy}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
let ret = iface_reload_config(phydev, config, old_config);
|
||||
if (ret) {
|
||||
iface_update_supplicant_macaddr(phy, config);
|
||||
hostapd.printf(`Reloaded settings for phy ${phy}`);
|
||||
return 0;
|
||||
}
|
||||
} catch (e) {
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
|
||||
hostapd.printf(`Restart interface for phy ${phy}`);
|
||||
return iface_restart(phy, config, old_config);
|
||||
let ret = iface_restart(phydev, config, old_config);
|
||||
iface_update_supplicant_macaddr(phy, config);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function config_add_bss(config, name)
|
||||
@@ -268,16 +583,28 @@ function iface_load_config(filename)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val[0] == "#num_global_macaddr" ||
|
||||
val[0] == "mbssid")
|
||||
config[val[0]] = int(val[1]);
|
||||
|
||||
push(config.radio.data, line);
|
||||
}
|
||||
|
||||
while ((line = trim(f.read("line"))) != null) {
|
||||
if (line == "#default_macaddr")
|
||||
bss.default_macaddr = true;
|
||||
|
||||
let val = split(line, "=", 2);
|
||||
if (!val[0])
|
||||
continue;
|
||||
|
||||
if (val[0] == "bssid")
|
||||
bss.bssid = val[1];
|
||||
if (val[0] == "bssid") {
|
||||
bss.bssid = lc(val[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val[0] == "nas_identifier")
|
||||
bss.nasid = val[1];
|
||||
|
||||
if (val[0] == "bss") {
|
||||
bss = config_add_bss(config, val[1]);
|
||||
@@ -294,28 +621,33 @@ function iface_load_config(filename)
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
function ex_wrap(func) {
|
||||
return (req) => {
|
||||
try {
|
||||
let ret = func(req);
|
||||
return ret;
|
||||
} catch(e) {
|
||||
hostapd.printf(`Exception in ubus function: ${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
};
|
||||
}
|
||||
|
||||
let main_obj = {
|
||||
reload: {
|
||||
args: {
|
||||
phy: "",
|
||||
},
|
||||
call: function(req) {
|
||||
try {
|
||||
let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
||||
for (let phy_name in phy_list) {
|
||||
let phy = hostapd.data.config[phy_name];
|
||||
let config = iface_load_config(phy.orig_file);
|
||||
iface_set_config(phy_name, config);
|
||||
}
|
||||
} catch(e) {
|
||||
hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
call: ex_wrap(function(req) {
|
||||
let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
||||
for (let phy_name in phy_list) {
|
||||
let phy = hostapd.data.config[phy_name];
|
||||
let config = iface_load_config(phy.orig_file);
|
||||
iface_set_config(phy_name, config);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
apsta_state: {
|
||||
args: {
|
||||
@@ -326,7 +658,7 @@ let main_obj = {
|
||||
csa: true,
|
||||
csa_count: 0,
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (req.args.up == null || !req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@@ -344,34 +676,10 @@ let main_obj = {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let freq = req.args.frequency;
|
||||
if (!freq)
|
||||
if (!req.args.frequency)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let sec_offset = req.args.sec_chan_offset;
|
||||
if (sec_offset != -1 && sec_offset != 1)
|
||||
sec_offset = 0;
|
||||
|
||||
let width = 0;
|
||||
for (let line in config.radio.data) {
|
||||
if (!sec_offset && match(line, /^ht_capab=.*HT40/)) {
|
||||
sec_offset = null; // auto-detect
|
||||
continue;
|
||||
}
|
||||
|
||||
let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
val = int(val[2]);
|
||||
if (val > width)
|
||||
width = val;
|
||||
}
|
||||
|
||||
if (freq < 4000)
|
||||
width = 0;
|
||||
|
||||
let freq_info = hostapd.freq_info(freq, sec_offset, width);
|
||||
let freq_info = iface_freq_info(iface, config, req.args);
|
||||
if (!freq_info)
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
|
||||
@@ -380,14 +688,34 @@ let main_obj = {
|
||||
freq_info.csa_count = req.args.csa_count ?? 10;
|
||||
ret = iface.switch_channel(freq_info);
|
||||
} else {
|
||||
iface.stop();
|
||||
ret = iface.start(freq_info);
|
||||
}
|
||||
if (!ret)
|
||||
return libubus.STATUS_UNKNOWN_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
config_get_macaddr_list: {
|
||||
args: {
|
||||
phy: ""
|
||||
},
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let ret = {
|
||||
macaddr: [],
|
||||
};
|
||||
|
||||
let config = hostapd.data.config[phy];
|
||||
if (!config)
|
||||
return ret;
|
||||
|
||||
ret.macaddr = map(config.bss, (bss) => bss.bssid);
|
||||
return ret;
|
||||
})
|
||||
},
|
||||
config_set: {
|
||||
args: {
|
||||
@@ -395,7 +723,7 @@ let main_obj = {
|
||||
config: "",
|
||||
prev_config: "",
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
let phy = req.args.phy;
|
||||
let file = req.args.config;
|
||||
let prev_file = req.args.prev_config;
|
||||
@@ -403,34 +731,29 @@ let main_obj = {
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
try {
|
||||
if (prev_file && !hostapd.data.config[phy]) {
|
||||
let config = iface_load_config(prev_file);
|
||||
if (config)
|
||||
config.radio.data = [];
|
||||
hostapd.data.config[phy] = config;
|
||||
}
|
||||
|
||||
let config = iface_load_config(file);
|
||||
|
||||
hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
||||
iface_set_config(phy, config);
|
||||
} catch(e) {
|
||||
hostapd.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
if (prev_file && !hostapd.data.config[phy]) {
|
||||
let config = iface_load_config(prev_file);
|
||||
if (config)
|
||||
config.radio.data = [];
|
||||
hostapd.data.config[phy] = config;
|
||||
}
|
||||
|
||||
let config = iface_load_config(file);
|
||||
|
||||
hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
||||
iface_set_config(phy, config);
|
||||
|
||||
return {
|
||||
pid: hostapd.getpid()
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
config_add: {
|
||||
args: {
|
||||
iface: "",
|
||||
config: "",
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (!req.args.iface || !req.args.config)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
@@ -440,19 +763,19 @@ let main_obj = {
|
||||
return {
|
||||
pid: hostapd.getpid()
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
config_remove: {
|
||||
args: {
|
||||
iface: ""
|
||||
},
|
||||
call: function(req) {
|
||||
call: ex_wrap(function(req) {
|
||||
if (!req.args.iface)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
hostapd.remove_iface(req.args.iface);
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc";
|
||||
import { vlist_new, is_equal, wdev_create, wdev_remove, 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 new_config = shift(ARGV);
|
||||
let command = shift(ARGV);
|
||||
let phydev;
|
||||
|
||||
const mesh_params = [
|
||||
"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",
|
||||
@@ -33,6 +36,11 @@ function iface_start(wdev)
|
||||
system([ "ip", "link", "set", "dev", ifname, "down" ]);
|
||||
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);
|
||||
system([ "ip", "link", "set", "dev", ifname, "up" ]);
|
||||
if (wdev.freq)
|
||||
@@ -47,7 +55,7 @@ function iface_start(wdev)
|
||||
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 [ "beacon-interval", "mcast-rate" ])
|
||||
for (let key in [ "mcast-rate", "beacon-interval" ])
|
||||
if (wdev[key])
|
||||
push(cmd, key, wdev[key]);
|
||||
system(cmd);
|
||||
@@ -114,43 +122,86 @@ function add_existing(phy, config)
|
||||
}
|
||||
}
|
||||
|
||||
function usage()
|
||||
{
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
|
||||
|
||||
let statefile = `/var/run/wdev-${phy}.json`;
|
||||
|
||||
for (let dev in ARGV)
|
||||
keep_devices[dev] = true;
|
||||
|
||||
if (!phy || !new_config) {
|
||||
warn(`Usage: ${basename(sourcepath())} <phy> <config> [<device]...]\n`);
|
||||
Commands:
|
||||
set_config <config> [<device]...] - set phy configuration
|
||||
get_macaddr <id> - get phy MAC address for vif index <id>
|
||||
`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!readfile(`/sys/class/ieee80211/${phy}/index`)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
add_ifname(new_config);
|
||||
config.update(new_config);
|
||||
|
||||
drop_inactive(config.data);
|
||||
delete_ifname(config.data);
|
||||
writefile(statefile, sprintf("%J", config.data));
|
||||
commands[command](ARGV);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
let libubus = require("ubus");
|
||||
import { open, readfile } from "fs";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new } from "common";
|
||||
import { wdev_create, wdev_remove, is_equal, vlist_new, phy_open } from "common";
|
||||
|
||||
let ubus = libubus.connect();
|
||||
|
||||
wpas.data.config = {};
|
||||
wpas.data.iface_phy = {};
|
||||
wpas.data.macaddr_list = {};
|
||||
|
||||
function iface_stop(iface)
|
||||
{
|
||||
@@ -20,16 +21,23 @@ function iface_stop(iface)
|
||||
iface.running = false;
|
||||
}
|
||||
|
||||
function iface_start(phy, iface)
|
||||
function iface_start(phydev, iface, macaddr_list)
|
||||
{
|
||||
let phy = phydev.name;
|
||||
|
||||
if (iface.running)
|
||||
return;
|
||||
|
||||
let ifname = iface.config.iface;
|
||||
let wdev_config = {};
|
||||
for (let field in iface.config)
|
||||
wdev_config[field] = iface.config[field];
|
||||
if (!wdev_config.macaddr)
|
||||
wdev_config.macaddr = phydev.macaddr_next();
|
||||
|
||||
wpas.data.iface_phy[ifname] = phy;
|
||||
wdev_remove(ifname);
|
||||
let ret = wdev_create(phy, ifname, iface.config);
|
||||
let ret = wdev_create(phy, ifname, wdev_config);
|
||||
if (ret)
|
||||
wpas.printf(`Failed to create device ${ifname}: ${ret}`);
|
||||
wpas.add_iface(iface.config);
|
||||
@@ -43,6 +51,11 @@ function iface_cb(new_if, old_if)
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_if && old_if)
|
||||
wpas.printf(`Update configuration for interface ${old_if.config.iface}`);
|
||||
else if (old_if)
|
||||
wpas.printf(`Remove interface ${old_if.config.iface}`);
|
||||
|
||||
if (old_if)
|
||||
iface_stop(old_if);
|
||||
}
|
||||
@@ -73,9 +86,22 @@ function set_config(phy_name, config_list)
|
||||
function start_pending(phy_name)
|
||||
{
|
||||
let phy = wpas.data.config[phy_name];
|
||||
let ubus = wpas.data.ubus;
|
||||
|
||||
if (!phy || !phy.data)
|
||||
return;
|
||||
|
||||
let phydev = phy_open(phy_name);
|
||||
if (!phydev) {
|
||||
wpas.printf(`Could not open phy ${phy_name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let macaddr_list = wpas.data.macaddr_list[phy_name];
|
||||
phydev.macaddr_init(macaddr_list);
|
||||
|
||||
for (let ifname in phy.data)
|
||||
iface_start(phy_name, phy.data[ifname]);
|
||||
iface_start(phydev, phy.data[ifname]);
|
||||
}
|
||||
|
||||
let main_obj = {
|
||||
@@ -106,6 +132,55 @@ let main_obj = {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
phy_set_macaddr_list: {
|
||||
args: {
|
||||
phy: "",
|
||||
macaddr: [],
|
||||
},
|
||||
call: function(req) {
|
||||
let phy = req.args.phy;
|
||||
if (!phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
wpas.data.macaddr_list[phy] = req.args.macaddr;
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
phy_status: {
|
||||
args: {
|
||||
phy: ""
|
||||
},
|
||||
call: function(req) {
|
||||
if (!req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
let phy = wpas.data.config[req.args.phy];
|
||||
if (!phy)
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
|
||||
for (let ifname in phy.data) {
|
||||
try {
|
||||
let iface = wpas.interfaces[ifname];
|
||||
if (!iface)
|
||||
continue;
|
||||
|
||||
let status = iface.status();
|
||||
if (!status)
|
||||
continue;
|
||||
|
||||
if (status.state == "INTERFACE_DISABLED")
|
||||
continue;
|
||||
|
||||
status.ifname = ifname;
|
||||
return status;
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return libubus.STATUS_NOT_FOUND;
|
||||
}
|
||||
},
|
||||
config_set: {
|
||||
args: {
|
||||
phy: "",
|
||||
@@ -116,6 +191,7 @@ let main_obj = {
|
||||
if (!req.args.phy)
|
||||
return libubus.STATUS_INVALID_ARGUMENT;
|
||||
|
||||
wpas.printf(`Set new config for phy ${req.args.phy}`);
|
||||
try {
|
||||
if (req.args.config)
|
||||
set_config(req.args.phy, req.args.config);
|
||||
@@ -188,6 +264,7 @@ function iface_hostapd_notify(phy, ifname, iface, state)
|
||||
switch (state) {
|
||||
case "DISCONNECTED":
|
||||
case "AUTHENTICATING":
|
||||
case "SCANNING":
|
||||
msg.up = false;
|
||||
break;
|
||||
case "INTERFACE_DISABLED":
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From: Harshitha Prem <quic_hprem@quicinc.com>
|
||||
Date: Wed, 22 Feb 2023 09:29:01 +0530
|
||||
Subject: [PATCH] nl80211: Add frequency info in start AP command
|
||||
|
||||
When ACS is configured in multiple BSS case, sometimes a virtual AP
|
||||
interface does not come up as the channel context information between
|
||||
different BSSs of the same band does not match.
|
||||
|
||||
Same behavior is observed in case of multiple band/hardware under a
|
||||
single wiphy, when we bring up multiple virtual interface in various
|
||||
bands simultaneously and the kernel maps a random channel as it has more
|
||||
than one channel context, e.g., say a 2.4 GHz channel to a 5 GHz virtual
|
||||
AP interface when the start AP command is sent. This is because the
|
||||
frequency information is not present in the command.
|
||||
|
||||
Add the frequency information into the start AP netlink command so that
|
||||
the kernel maps the appropriate channel context by parsing it instead of
|
||||
using a previous set channel information.
|
||||
|
||||
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -167,6 +167,8 @@ static int nl80211_send_frame_cmd(struct
|
||||
const u16 *csa_offs, size_t csa_offs_len);
|
||||
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
|
||||
int report);
|
||||
+static int nl80211_put_freq_params(struct nl_msg *msg,
|
||||
+ const struct hostapd_freq_params *freq);
|
||||
|
||||
#define IFIDX_ANY -1
|
||||
|
||||
@@ -4717,6 +4719,9 @@ static int wpa_driver_nl80211_set_ap(voi
|
||||
nla_nest_end(msg, spr);
|
||||
}
|
||||
|
||||
+ if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
if (params->freq && params->freq->he_enabled) {
|
||||
struct nlattr *bss_color;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 10:53:50 +0200
|
||||
Subject: [PATCH] driver_nl80211: fix setting QoS map on secondary BSSs
|
||||
|
||||
The setting is per-BSS, not per PHY
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -10045,7 +10045,7 @@ static int nl80211_set_qos_map(void *pri
|
||||
wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
|
||||
qos_map_set, qos_map_set_len);
|
||||
|
||||
- if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) ||
|
||||
+ if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_QOS_MAP)) ||
|
||||
nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
@@ -0,0 +1,18 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 11:28:03 +0200
|
||||
Subject: [PATCH] driver_nl80211: update drv->ifindex on removing the first
|
||||
BSS
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -8003,6 +8003,7 @@ static int wpa_driver_nl80211_if_remove(
|
||||
if (drv->first_bss->next) {
|
||||
drv->first_bss = drv->first_bss->next;
|
||||
drv->ctx = drv->first_bss->ctx;
|
||||
+ drv->ifindex = drv->first_bss->ifindex;
|
||||
os_free(bss);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
|
||||
@@ -1,5 +1,7 @@
|
||||
--- a/hostapd/Makefile
|
||||
+++ b/hostapd/Makefile
|
||||
Index: hostapd-2021-02-20-59e9794c/hostapd/Makefile
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/hostapd/Makefile
|
||||
+++ hostapd-2021-02-20-59e9794c/hostapd/Makefile
|
||||
@@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common
|
||||
|
||||
OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
||||
@@ -13,8 +15,10 @@
|
||||
|
||||
ifdef CONFIG_CODE_COVERAGE
|
||||
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
|
||||
--- a/src/ap/hostapd.h
|
||||
+++ b/src/ap/hostapd.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "utils/list.h"
|
||||
#include "ap_config.h"
|
||||
@@ -39,8 +43,10 @@
|
||||
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||
struct hostapd_iface * hostapd_alloc_iface(void);
|
||||
--- a/src/ap/hostapd.c
|
||||
+++ b/src/ap/hostapd.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
||||
@@ -376,6 +376,7 @@ void hostapd_free_hapd_data(struct hosta
|
||||
hapd->beacon_set_done = 0;
|
||||
|
||||
@@ -82,8 +88,10 @@
|
||||
hostapd_interface_deinit(iface);
|
||||
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
||||
__func__, driver, drv_priv);
|
||||
--- a/src/ap/ieee802_11.c
|
||||
+++ b/src/ap/ieee802_11.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_11.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_11.c
|
||||
@@ -3421,13 +3421,18 @@ static void handle_auth(struct hostapd_d
|
||||
u16 auth_alg, auth_transaction, status_code;
|
||||
u16 resp = WLAN_STATUS_SUCCESS;
|
||||
@@ -170,8 +178,10 @@
|
||||
sta = ap_get_sta(hapd, mgmt->sa);
|
||||
if (sta == NULL) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
|
||||
--- a/src/ap/beacon.c
|
||||
+++ b/src/ap/beacon.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
||||
@@ -823,6 +823,12 @@ void handle_probe_req(struct hostapd_dat
|
||||
u16 csa_offs[2];
|
||||
size_t csa_offs_len;
|
||||
@@ -198,8 +208,10 @@
|
||||
/* TODO: verify that supp_rates contains at least one matching rate
|
||||
* with AP configuration */
|
||||
|
||||
--- a/src/ap/drv_callbacks.c
|
||||
+++ b/src/ap/drv_callbacks.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/drv_callbacks.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/drv_callbacks.c
|
||||
@@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d
|
||||
u16 reason = WLAN_REASON_UNSPECIFIED;
|
||||
int status = WLAN_STATUS_SUCCESS;
|
||||
@@ -224,8 +236,22 @@
|
||||
#ifdef CONFIG_P2P
|
||||
if (elems.p2p) {
|
||||
wpabuf_free(sta->p2p_ie);
|
||||
--- a/src/ap/sta_info.c
|
||||
+++ b/src/ap/sta_info.c
|
||||
@@ -981,9 +991,11 @@ void hostapd_event_ch_switch(struct host
|
||||
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||
"freq=%d dfs=%d", freq, is_dfs);
|
||||
+ hostapd_ubus_notify_csa(hapd, freq);
|
||||
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
|
||||
"freq=%d dfs=%d", freq, is_dfs);
|
||||
+ hostapd_ubus_notify_csa(hapd, freq);
|
||||
} else if (is_dfs &&
|
||||
hostapd_is_dfs_required(hapd->iface) &&
|
||||
!hostapd_is_dfs_chan_available(hapd->iface) &&
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
||||
@@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo
|
||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
||||
@@ -304,8 +330,10 @@
|
||||
|
||||
if (hapd->msg_ctx_parent &&
|
||||
hapd->msg_ctx_parent != hapd->msg_ctx)
|
||||
--- a/src/ap/wpa_auth_glue.c
|
||||
+++ b/src/ap/wpa_auth_glue.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_glue.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_glue.c
|
||||
@@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure
|
||||
struct hostapd_data *hapd = ctx;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
|
||||
@@ -314,8 +342,10 @@
|
||||
}
|
||||
|
||||
|
||||
--- a/wpa_supplicant/Makefile
|
||||
+++ b/wpa_supplicant/Makefile
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/Makefile
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/Makefile
|
||||
@@ -169,6 +169,13 @@ ifdef CONFIG_EAPOL_TEST
|
||||
CFLAGS += -Werror -DEAPOL_TEST
|
||||
endif
|
||||
@@ -340,8 +370,10 @@
|
||||
endif
|
||||
|
||||
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
|
||||
--- a/wpa_supplicant/wpa_supplicant.c
|
||||
+++ b/wpa_supplicant/wpa_supplicant.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant.c
|
||||
@@ -6943,6 +6943,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
||||
}
|
||||
#endif /* CONFIG_P2P */
|
||||
@@ -373,8 +405,10 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/wpa_supplicant/wpa_supplicant_i.h
|
||||
+++ b/wpa_supplicant/wpa_supplicant_i.h
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wpa_supplicant_i.h
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wpa_supplicant_i.h
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "wps/wps_defs.h"
|
||||
#include "config_ssid.h"
|
||||
@@ -400,8 +434,10 @@
|
||||
#ifdef CONFIG_MATCH_IFACE
|
||||
int matched;
|
||||
#endif /* CONFIG_MATCH_IFACE */
|
||||
--- a/wpa_supplicant/wps_supplicant.c
|
||||
+++ b/wpa_supplicant/wps_supplicant.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/wps_supplicant.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/wps_supplicant.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "p2p/p2p.h"
|
||||
#include "p2p_supplicant.h"
|
||||
@@ -419,8 +455,10 @@
|
||||
if (wpa_s->conf->wps_cred_processing == 1)
|
||||
return 0;
|
||||
|
||||
--- a/wpa_supplicant/main.c
|
||||
+++ b/wpa_supplicant/main.c
|
||||
Index: hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/wpa_supplicant/main.c
|
||||
+++ hostapd-2021-02-20-59e9794c/wpa_supplicant/main.c
|
||||
@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
for (;;) {
|
||||
@@ -440,8 +478,10 @@
|
||||
case 'o':
|
||||
params.override_driver = optarg;
|
||||
break;
|
||||
--- a/src/ap/rrm.c
|
||||
+++ b/src/ap/rrm.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/rrm.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/rrm.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/rrm.c
|
||||
@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report
|
||||
return;
|
||||
wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
|
||||
@@ -452,8 +492,10 @@
|
||||
}
|
||||
|
||||
|
||||
--- a/src/ap/vlan_init.c
|
||||
+++ b/src/ap/vlan_init.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/vlan_init.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/vlan_init.c
|
||||
@@ -22,6 +22,7 @@
|
||||
static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||
int existsok)
|
||||
@@ -490,8 +532,10 @@
|
||||
return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
||||
}
|
||||
|
||||
--- a/src/ap/dfs.c
|
||||
+++ b/src/ap/dfs.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/dfs.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/dfs.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/dfs.c
|
||||
@@ -1226,6 +1226,8 @@ int hostapd_dfs_nop_finished(struct host
|
||||
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
||||
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
||||
@@ -501,8 +545,10 @@
|
||||
/* Proceed only if DFS is not offloaded to the driver */
|
||||
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
||||
return 0;
|
||||
--- a/src/ap/airtime_policy.c
|
||||
+++ b/src/ap/airtime_policy.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/airtime_policy.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/airtime_policy.c
|
||||
@@ -108,8 +108,14 @@ static void set_sta_weights(struct hosta
|
||||
{
|
||||
struct sta_info *sta;
|
||||
@@ -532,8 +578,10 @@
|
||||
if (weight)
|
||||
return sta_set_airtime_weight(hapd, sta, weight);
|
||||
}
|
||||
--- a/src/ap/sta_info.h
|
||||
+++ b/src/ap/sta_info.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
||||
@@ -323,6 +323,7 @@ struct sta_info {
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
#ifdef CONFIG_AIRTIME_POLICY
|
||||
@@ -542,8 +590,10 @@
|
||||
struct os_reltime backlogged_until;
|
||||
#endif /* CONFIG_AIRTIME_POLICY */
|
||||
|
||||
--- a/src/ap/wnm_ap.c
|
||||
+++ b/src/ap/wnm_ap.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wnm_ap.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wnm_ap.c
|
||||
@@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt
|
||||
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||
pos, end - pos);
|
||||
@@ -582,8 +632,10 @@
|
||||
wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
||||
pos, end - pos);
|
||||
}
|
||||
--- a/src/utils/eloop.c
|
||||
+++ b/src/utils/eloop.c
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.c
|
||||
@@ -77,6 +77,9 @@ struct eloop_sock_table {
|
||||
struct eloop_data {
|
||||
int max_sock;
|
||||
@@ -632,8 +684,10 @@
|
||||
|
||||
void eloop_terminate(void)
|
||||
{
|
||||
--- a/src/utils/eloop.h
|
||||
+++ b/src/utils/eloop.h
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/eloop.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/utils/eloop.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/eloop.h
|
||||
@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo
|
||||
*/
|
||||
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
|
||||
@@ -663,8 +717,10 @@
|
||||
/**
|
||||
* eloop_run - Start the event loop
|
||||
*
|
||||
Index: hostapd-2021-02-20-59e9794c/src/utils/uloop.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/src/utils/uloop.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/utils/uloop.c
|
||||
@@ -0,0 +1,64 @@
|
||||
+#include <libubox/uloop.h>
|
||||
+#include "includes.h"
|
||||
|
||||
@@ -287,7 +287,33 @@
|
||||
|
||||
--- a/src/drivers/driver.h
|
||||
+++ b/src/drivers/driver.h
|
||||
@@ -5827,6 +5827,7 @@ union wpa_event_data {
|
||||
@@ -3357,6 +3357,25 @@ struct wpa_driver_ops {
|
||||
const char *ifname);
|
||||
|
||||
/**
|
||||
+ * if_rename - Rename a virtual interface
|
||||
+ * @priv: Private driver interface data
|
||||
+ * @type: Interface type
|
||||
+ * @ifname: Interface name of the virtual interface to be renamed
|
||||
+ * (NULL when renaming the AP BSS interface)
|
||||
+ * @new_name: New interface name of the virtual interface
|
||||
+ * Returns: 0 on success, -1 on failure
|
||||
+ */
|
||||
+ int (*if_rename)(void *priv, enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name);
|
||||
+
|
||||
+ /**
|
||||
+ * set_first_bss - Make a virtual interface the first (primary) bss
|
||||
+ * @priv: Private driver interface data
|
||||
+ * Returns: 0 on success, -1 on failure
|
||||
+ */
|
||||
+ int (*set_first_bss)(void *priv);
|
||||
+
|
||||
+ /**
|
||||
* set_sta_vlan - Bind a station into a specific interface (AP only)
|
||||
* @priv: Private driver interface data
|
||||
* @ifname: Interface (main or virtual BSS or VLAN)
|
||||
@@ -5827,6 +5846,7 @@ union wpa_event_data {
|
||||
|
||||
/**
|
||||
* struct ch_switch
|
||||
@@ -295,7 +321,7 @@
|
||||
* @freq: Frequency of new channel in MHz
|
||||
* @ht_enabled: Whether this is an HT channel
|
||||
* @ch_offset: Secondary channel offset
|
||||
@@ -5835,6 +5836,7 @@ union wpa_event_data {
|
||||
@@ -5835,6 +5855,7 @@ union wpa_event_data {
|
||||
* @cf2: Center frequency 2
|
||||
*/
|
||||
struct ch_switch {
|
||||
@@ -348,3 +374,187 @@
|
||||
switch (event) {
|
||||
case EVENT_AUTH:
|
||||
#ifdef CONFIG_FST
|
||||
--- a/src/ap/ap_drv_ops.h
|
||||
+++ b/src/ap/ap_drv_ops.h
|
||||
@@ -367,6 +367,23 @@ static inline int hostapd_drv_stop_ap(st
|
||||
return hapd->driver->stop_ap(hapd->drv_priv);
|
||||
}
|
||||
|
||||
+static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
|
||||
+ enum wpa_driver_if_type type,
|
||||
+ const char *ifname,
|
||||
+ const char *new_name)
|
||||
+{
|
||||
+ if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
|
||||
+ return -1;
|
||||
+ return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
|
||||
+}
|
||||
+
|
||||
+static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
|
||||
+{
|
||||
+ if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
|
||||
+ return 0;
|
||||
+ return hapd->driver->set_first_bss(hapd->drv_priv);
|
||||
+}
|
||||
+
|
||||
static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
|
||||
struct wpa_channel_info *ci)
|
||||
{
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -1222,7 +1222,7 @@ static void wpa_driver_nl80211_event_rtm
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
|
||||
namebuf, ifname);
|
||||
- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
|
||||
+ if (drv->first_bss->ifindex != ifi->ifi_index) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Not the main interface (%s) - do not indicate interface down",
|
||||
drv->first_bss->ifname);
|
||||
@@ -1258,7 +1258,7 @@ static void wpa_driver_nl80211_event_rtm
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
|
||||
namebuf, ifname);
|
||||
- if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
|
||||
+ if (drv->first_bss->ifindex != ifi->ifi_index) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Not the main interface (%s) - do not indicate interface up",
|
||||
drv->first_bss->ifname);
|
||||
@@ -7609,6 +7609,7 @@ static void *i802_init(struct hostapd_da
|
||||
char master_ifname[IFNAMSIZ];
|
||||
int ifindex, br_ifindex = 0;
|
||||
int br_added = 0;
|
||||
+ int err;
|
||||
|
||||
bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
|
||||
params->global_priv, 1,
|
||||
@@ -7668,21 +7669,17 @@ static void *i802_init(struct hostapd_da
|
||||
(params->num_bridge == 0 || !params->bridge[0]))
|
||||
add_ifidx(drv, br_ifindex, drv->ifindex);
|
||||
|
||||
- if (bss->added_if_into_bridge || bss->already_in_bridge) {
|
||||
- int err;
|
||||
-
|
||||
- drv->rtnl_sk = nl_socket_alloc();
|
||||
- if (drv->rtnl_sk == NULL) {
|
||||
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
|
||||
- goto failed;
|
||||
- }
|
||||
+ drv->rtnl_sk = nl_socket_alloc();
|
||||
+ if (drv->rtnl_sk == NULL) {
|
||||
+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
|
||||
+ goto failed;
|
||||
+ }
|
||||
|
||||
- err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
|
||||
- if (err) {
|
||||
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
|
||||
- nl_geterror(err));
|
||||
- goto failed;
|
||||
- }
|
||||
+ err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
|
||||
+ if (err) {
|
||||
+ wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
|
||||
+ nl_geterror(err));
|
||||
+ goto failed;
|
||||
}
|
||||
|
||||
if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
|
||||
@@ -8041,6 +8038,50 @@ static int wpa_driver_nl80211_if_remove(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int wpa_driver_nl80211_if_rename(struct i802_bss *bss,
|
||||
+ enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name)
|
||||
+{
|
||||
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
+ struct ifinfomsg ifi = {
|
||||
+ .ifi_family = AF_UNSPEC,
|
||||
+ .ifi_index = bss->ifindex,
|
||||
+ };
|
||||
+ struct nl_msg *msg;
|
||||
+ int res = -ENOMEM;
|
||||
+
|
||||
+ if (ifname)
|
||||
+ ifi.ifi_index = if_nametoindex(ifname);
|
||||
+
|
||||
+ msg = nlmsg_alloc_simple(RTM_SETLINK, 0);
|
||||
+ if (!msg)
|
||||
+ return res;
|
||||
+
|
||||
+ if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (nla_put_string(msg, IFLA_IFNAME, new_name))
|
||||
+ goto out;
|
||||
+
|
||||
+ res = nl_send_auto_complete(drv->rtnl_sk, msg);
|
||||
+ if (res < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ res = nl_wait_for_ack(drv->rtnl_sk);
|
||||
+ if (res) {
|
||||
+ wpa_printf(MSG_INFO,
|
||||
+ "nl80211: Renaming device %s to %s failed: %s",
|
||||
+ ifname ? ifname : bss->ifname, new_name, nl_geterror(res));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (type == WPA_IF_AP_BSS && !ifname)
|
||||
+ os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname));
|
||||
+
|
||||
+out:
|
||||
+ nlmsg_free(msg);
|
||||
+ return res;
|
||||
+}
|
||||
|
||||
static int cookie_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
@@ -9385,6 +9426,37 @@ static int driver_nl80211_if_remove(void
|
||||
}
|
||||
|
||||
|
||||
+static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type,
|
||||
+ const char *ifname, const char *new_name)
|
||||
+{
|
||||
+ struct i802_bss *bss = priv;
|
||||
+ return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int driver_nl80211_set_first_bss(void *priv)
|
||||
+{
|
||||
+ struct i802_bss *bss = priv, *tbss;
|
||||
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
+
|
||||
+ if (drv->first_bss == bss)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
|
||||
+ if (tbss->next != bss)
|
||||
+ continue;
|
||||
+
|
||||
+ tbss->next = bss->next;
|
||||
+ bss->next = drv->first_bss;
|
||||
+ drv->first_bss = bss;
|
||||
+ drv->ctx = bss->ctx;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
|
||||
size_t data_len, int noack,
|
||||
unsigned int freq,
|
||||
@@ -11967,6 +12039,8 @@ const struct wpa_driver_ops wpa_driver_n
|
||||
.set_acl = wpa_driver_nl80211_set_acl,
|
||||
.if_add = wpa_driver_nl80211_if_add,
|
||||
.if_remove = driver_nl80211_if_remove,
|
||||
+ .if_rename = driver_nl80211_if_rename,
|
||||
+ .set_first_bss = driver_nl80211_set_first_bss,
|
||||
.send_mlme = driver_nl80211_send_mlme,
|
||||
.get_hw_feature_data = nl80211_get_hw_feature_data,
|
||||
.sta_add = wpa_driver_nl80211_sta_add,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
--- a/src/ap/x_snoop.c
|
||||
+++ b/src/ap/x_snoop.c
|
||||
@@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
@@ -31,28 +31,31 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -29,13 +29,20 @@
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable proxyarp on the bridge port");
|
||||
return -1;
|
||||
@@ -52,7 +54,8 @@ int x_snoop_init(struct hostapd_data *ha
|
||||
}
|
||||
|
||||
if (hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
|
||||
- 1)) {
|
||||
+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable accepting gratuitous ARP on the bridge");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6
|
||||
- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
||||
+ if (!conf->snoop_iface[0] &&
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, NULL, 1)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to enable multicast snooping on the bridge");
|
||||
return -1;
|
||||
@@ -44,15 +51,27 @@
|
||||
struct hostapd_bss_config *conf = hapd->conf;
|
||||
struct l2_packet_data *l2;
|
||||
+ const char *ifname = conf->bridge;
|
||||
|
||||
- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
+
|
||||
+ if (conf->snoop_iface[0])
|
||||
+ ifname = conf->snoop_iface;
|
||||
+
|
||||
|
||||
- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
+ l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1);
|
||||
if (l2 == NULL) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"x_snoop: Failed to initialize L2 packet processing %s",
|
||||
@@ -125,7 +132,10 @@ void x_snoop_mcast_to_ucast_convert_send
|
||||
|
||||
void x_snoop_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
- hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT, 0);
|
||||
+ struct hostapd_bss_config *conf = hapd->conf;
|
||||
+
|
||||
+ hostapd_drv_br_set_net_param(hapd, DRV_BR_NET_PARAM_GARP_ACCEPT,
|
||||
+ conf->snoop_iface[0] ? conf->snoop_iface : NULL, 0);
|
||||
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 0);
|
||||
hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 0);
|
||||
}
|
||||
--- a/hostapd/config_file.c
|
||||
+++ b/hostapd/config_file.c
|
||||
@@ -2343,6 +2343,8 @@ static int hostapd_config_fill(struct ho
|
||||
@@ -64,3 +83,55 @@
|
||||
} else if (os_strcmp(buf, "vlan_bridge") == 0) {
|
||||
os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
|
||||
} else if (os_strcmp(buf, "wds_bridge") == 0) {
|
||||
--- a/src/ap/ap_drv_ops.h
|
||||
+++ b/src/ap/ap_drv_ops.h
|
||||
@@ -340,12 +340,12 @@ static inline int hostapd_drv_br_port_se
|
||||
|
||||
static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
|
||||
enum drv_br_net_param param,
|
||||
- unsigned int val)
|
||||
+ const char *ifname, unsigned int val)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
||||
hapd->driver->br_set_net_param == NULL)
|
||||
return -1;
|
||||
- return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
|
||||
+ return hapd->driver->br_set_net_param(hapd->drv_priv, param, ifname, val);
|
||||
}
|
||||
|
||||
static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
||||
--- a/src/drivers/driver.h
|
||||
+++ b/src/drivers/driver.h
|
||||
@@ -3756,7 +3756,7 @@ struct wpa_driver_ops {
|
||||
* Returns: 0 on success, negative (<0) on failure
|
||||
*/
|
||||
int (*br_set_net_param)(void *priv, enum drv_br_net_param param,
|
||||
- unsigned int val);
|
||||
+ const char *ifname, unsigned int val);
|
||||
|
||||
/**
|
||||
* get_wowlan - Get wake-on-wireless status
|
||||
--- a/src/drivers/driver_nl80211.c
|
||||
+++ b/src/drivers/driver_nl80211.c
|
||||
@@ -10825,7 +10825,7 @@ static const char * drv_br_net_param_str
|
||||
|
||||
|
||||
static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
|
||||
- unsigned int val)
|
||||
+ const char *ifname, unsigned int val)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
char path[128];
|
||||
@@ -10851,8 +10851,11 @@ static int wpa_driver_br_set_net_param(v
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if (!ifname)
|
||||
+ ifname = bss->brname;
|
||||
+
|
||||
os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
|
||||
- ip_version, bss->brname, param_txt);
|
||||
+ ip_version, ifname, param_txt);
|
||||
|
||||
set_val:
|
||||
if (linux_write_system_file(path, val))
|
||||
|
||||
@@ -19,18 +19,6 @@
|
||||
|
||||
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -424,6 +424,9 @@ hostapd_bss_get_status(struct ubus_conte
|
||||
hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
||||
blobmsg_close_table(&b, dfs_table);
|
||||
|
||||
+ if (hapd->conf->uci_section)
|
||||
+ blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
+
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
--- a/src/ap/ap_config.c
|
||||
+++ b/src/ap/ap_config.c
|
||||
@@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host
|
||||
|
||||
@@ -50,42 +50,4 @@
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -306,6 +306,36 @@ hostapd_bss_get_clients(struct ubus_cont
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
|
||||
blobmsg_close_table(&b, r);
|
||||
blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
|
||||
+
|
||||
+ r = blobmsg_open_table(&b, "mcs");
|
||||
+ if (sta_driver_data.rx_hemcs) {
|
||||
+ blobmsg_add_u32(&b, "he", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs);
|
||||
+ } else if (sta_driver_data.rx_vhtmcs) {
|
||||
+ blobmsg_add_u32(&b, "vht", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs);
|
||||
+ } else {
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
+ }
|
||||
+ blobmsg_close_table(&b, r);
|
||||
+
|
||||
+ r = blobmsg_open_table(&b, "nss");
|
||||
+ if (sta_driver_data.rx_he_nss) {
|
||||
+ blobmsg_add_u32(&b, "he", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss);
|
||||
+ } else if (sta_driver_data.rx_vht_nss) {
|
||||
+ blobmsg_add_u32(&b, "vht", 1);
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss);
|
||||
+ } else {
|
||||
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
+ }
|
||||
+ blobmsg_close_table(&b, r);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
|
||||
|
||||
48
feeds/wifi-ax/hostapd/patches/999-ft-anonce.patch
Normal file
48
feeds/wifi-ax/hostapd/patches/999-ft-anonce.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_ft.c
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_ft.c
|
||||
@@ -3067,6 +3067,7 @@ static int wpa_ft_process_auth_req(struc
|
||||
size_t identity_len = 0, radius_cui_len = 0;
|
||||
int use_sha384;
|
||||
size_t pmk_r1_len, kdk_len;
|
||||
+ struct os_reltime now;
|
||||
|
||||
*resp_ies = NULL;
|
||||
*resp_ies_len = 0;
|
||||
@@ -3185,10 +3186,19 @@ pmk_r1_derived:
|
||||
os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len);
|
||||
sm->pmk_r1_len = pmk_r1_len;
|
||||
|
||||
- if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
- wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
- "ANonce");
|
||||
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
+ if (os_get_reltime(&now) < 0 ||
|
||||
+ os_reltime_expired(&now, &sm->ANonce_time, 1)) {
|
||||
+ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
|
||||
+ wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
|
||||
+ "ANonce");
|
||||
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
+ }
|
||||
+ sm->ANonce_time.sec = now.sec;
|
||||
+ sm->ANonce_time.usec = now.usec;
|
||||
+ wpa_printf(MSG_INFO, "FT: ANonce was randomized");
|
||||
+ } else {
|
||||
+ wpa_printf(MSG_INFO, "FT: ANonce has not expired");
|
||||
+
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
|
||||
Index: hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h
|
||||
===================================================================
|
||||
--- hostapd-2021-02-20-59e9794c.orig/src/ap/wpa_auth_i.h
|
||||
+++ hostapd-2021-02-20-59e9794c/src/ap/wpa_auth_i.h
|
||||
@@ -54,6 +54,7 @@ struct wpa_state_machine {
|
||||
bool MICVerified;
|
||||
bool GUpdateStationKeys;
|
||||
u8 ANonce[WPA_NONCE_LEN];
|
||||
+ struct os_reltime ANonce_time;
|
||||
u8 SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
@@ -61,28 +61,6 @@
|
||||
};
|
||||
|
||||
|
||||
--- a/src/ap/ubus.c
|
||||
+++ b/src/ap/ubus.c
|
||||
@@ -336,6 +336,9 @@ hostapd_bss_get_clients(struct ubus_cont
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
+
|
||||
+ if (sta->signal_mgmt)
|
||||
+ blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
@@ -457,6 +460,9 @@ hostapd_bss_get_status(struct ubus_conte
|
||||
if (hapd->conf->uci_section)
|
||||
blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
|
||||
+ if (hapd->signal_mgmt)
|
||||
+ blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt);
|
||||
+
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
--- a/src/ap/hostapd.h
|
||||
+++ b/src/ap/hostapd.h
|
||||
@@ -451,6 +451,7 @@ struct hostapd_data {
|
||||
|
||||
@@ -306,6 +306,39 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
|
||||
blobmsg_close_table(&b, r);
|
||||
blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
|
||||
|
||||
r = blobmsg_open_table(&b, "mcs");
|
||||
if (sta_driver_data.rx_hemcs) {
|
||||
blobmsg_add_u32(&b, "he", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_hemcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_hemcs);
|
||||
} else if (sta_driver_data.rx_vhtmcs) {
|
||||
blobmsg_add_u32(&b, "vht", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vhtmcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vhtmcs);
|
||||
} else {
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
|
||||
r = blobmsg_open_table(&b, "nss");
|
||||
if (sta_driver_data.rx_he_nss) {
|
||||
blobmsg_add_u32(&b, "he", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_he_nss);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_he_nss);
|
||||
} else if (sta_driver_data.rx_vht_nss) {
|
||||
blobmsg_add_u32(&b, "vht", 1);
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_vht_nss);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_vht_nss);
|
||||
} else {
|
||||
blobmsg_add_u32(&b, "rx", sta_driver_data.rx_mcs);
|
||||
blobmsg_add_u32(&b, "tx", sta_driver_data.tx_mcs);
|
||||
}
|
||||
blobmsg_close_table(&b, r);
|
||||
|
||||
if (sta->signal_mgmt)
|
||||
blobmsg_add_u32(&b, "signal_mgmt", sta->signal_mgmt);
|
||||
}
|
||||
|
||||
hostapd_parse_capab_blobmsg(sta);
|
||||
@@ -424,6 +457,12 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
||||
blobmsg_close_table(&b, dfs_table);
|
||||
|
||||
if (hapd->conf->uci_section)
|
||||
blobmsg_add_string(&b, "uci_section", hapd->conf->uci_section);
|
||||
|
||||
if (hapd->signal_mgmt)
|
||||
blobmsg_add_u32(&b, "signal_mgmt", hapd->signal_mgmt);
|
||||
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
@@ -1698,6 +1737,19 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *
|
||||
ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
|
||||
}
|
||||
|
||||
void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq)
|
||||
{
|
||||
if (!hapd->ubus.obj.has_subscribers)
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "ifname", hapd->conf->iface);
|
||||
blobmsg_add_u32(&b, "freq", freq);
|
||||
blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
|
||||
|
||||
ubus_notify(ctx, &hapd->ubus.obj, "channel-switch", b.head, -1);
|
||||
}
|
||||
|
||||
|
||||
void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta)
|
||||
{
|
||||
|
||||
1845
feeds/wifi-ax/hostapd/src/src/ap/ubus.c.orig
Normal file
1845
feeds/wifi-ax/hostapd/src/src/ap/ubus.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@ void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
||||
int hostapd_ubus_notify_bss_transition_query(
|
||||
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
||||
const u8 *candidate_list, u16 candidate_list_len);
|
||||
void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "beacon.h"
|
||||
#include "hw_features.h"
|
||||
#include "ap_drv_ops.h"
|
||||
#include "dfs.h"
|
||||
#include "acs.h"
|
||||
#include <libubox/uloop.h>
|
||||
|
||||
static uc_resource_type_t *global_type, *bss_type, *iface_type;
|
||||
@@ -109,6 +111,94 @@ uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct hostapd_vlan *
|
||||
bss_conf_find_vlan(struct hostapd_bss_config *bss, int id)
|
||||
{
|
||||
struct hostapd_vlan *vlan;
|
||||
|
||||
for (vlan = bss->vlan; vlan; vlan = vlan->next)
|
||||
if (vlan->vlan_id == id)
|
||||
return vlan;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
bss_conf_rename_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
||||
const char *ifname)
|
||||
{
|
||||
if (!strcmp(ifname, vlan->ifname))
|
||||
return 0;
|
||||
|
||||
hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, vlan->ifname, ifname);
|
||||
os_strlcpy(vlan->ifname, ifname, sizeof(vlan->ifname));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bss_reload_vlans(struct hostapd_data *hapd, struct hostapd_bss_config *bss)
|
||||
{
|
||||
struct hostapd_bss_config *old_bss = hapd->conf;
|
||||
struct hostapd_vlan *vlan, *vlan_new, *wildcard;
|
||||
char ifname[IFNAMSIZ + 1], vlan_ifname[IFNAMSIZ + 1], *pos;
|
||||
int ret;
|
||||
|
||||
vlan = bss_conf_find_vlan(old_bss, VLAN_ID_WILDCARD);
|
||||
wildcard = bss_conf_find_vlan(bss, VLAN_ID_WILDCARD);
|
||||
if (!!vlan != !!wildcard)
|
||||
return -1;
|
||||
|
||||
if (vlan && wildcard && strcmp(vlan->ifname, wildcard->ifname) != 0)
|
||||
strcpy(vlan->ifname, wildcard->ifname);
|
||||
else
|
||||
wildcard = NULL;
|
||||
|
||||
for (vlan = bss->vlan; vlan; vlan = vlan->next) {
|
||||
if (vlan->vlan_id == VLAN_ID_WILDCARD ||
|
||||
vlan->dynamic_vlan > 0)
|
||||
continue;
|
||||
|
||||
if (!bss_conf_find_vlan(old_bss, vlan->vlan_id))
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (vlan = old_bss->vlan; vlan; vlan = vlan->next) {
|
||||
if (vlan->vlan_id == VLAN_ID_WILDCARD)
|
||||
continue;
|
||||
|
||||
if (vlan->dynamic_vlan == 0) {
|
||||
vlan_new = bss_conf_find_vlan(bss, vlan->vlan_id);
|
||||
if (!vlan_new)
|
||||
return -1;
|
||||
|
||||
if (bss_conf_rename_vlan(hapd, vlan, vlan_new->ifname))
|
||||
return -1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!wildcard)
|
||||
continue;
|
||||
|
||||
os_strlcpy(ifname, wildcard->ifname, sizeof(ifname));
|
||||
pos = os_strchr(ifname, '#');
|
||||
if (!pos)
|
||||
return -1;
|
||||
|
||||
*pos++ = '\0';
|
||||
ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s%d%s",
|
||||
ifname, vlan->vlan_id, pos);
|
||||
if (os_snprintf_error(sizeof(vlan_ifname), ret))
|
||||
return -1;
|
||||
|
||||
if (bss_conf_rename_vlan(hapd, vlan, vlan_ifname))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
@@ -118,6 +208,7 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_config *conf;
|
||||
uc_value_t *file = uc_fn_arg(0);
|
||||
uc_value_t *index = uc_fn_arg(1);
|
||||
uc_value_t *files_only = uc_fn_arg(2);
|
||||
unsigned int i, idx = 0;
|
||||
int ret = -1;
|
||||
|
||||
@@ -129,9 +220,28 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
|
||||
iface = hapd->iface;
|
||||
conf = interfaces->config_read_cb(ucv_string_get(file));
|
||||
if (!conf || idx > conf->num_bss || !conf->bss[idx])
|
||||
if (!conf)
|
||||
goto out;
|
||||
|
||||
if (idx > conf->num_bss || !conf->bss[idx])
|
||||
goto free;
|
||||
|
||||
if (ucv_boolean_get(files_only)) {
|
||||
struct hostapd_bss_config *bss = conf->bss[idx];
|
||||
struct hostapd_bss_config *old_bss = hapd->conf;
|
||||
|
||||
#define swap_field(name) \
|
||||
do { \
|
||||
void *ptr = old_bss->name; \
|
||||
old_bss->name = bss->name; \
|
||||
bss->name = ptr; \
|
||||
} while (0)
|
||||
|
||||
swap_field(ssid.wpa_psk_file);
|
||||
ret = bss_reload_vlans(hapd, bss);
|
||||
goto done;
|
||||
}
|
||||
|
||||
hostapd_bss_deinit_no_free(hapd);
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hostapd_free_hapd_data(hapd);
|
||||
@@ -142,12 +252,14 @@ uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
||||
iface->conf->bss[i] = conf->bss[idx];
|
||||
hapd->conf = conf->bss[idx];
|
||||
conf->bss[idx] = old_bss;
|
||||
hostapd_config_free(conf);
|
||||
|
||||
hostapd_setup_bss(hapd, hapd == iface->bss[0], !iface->conf->multiple_bssid);
|
||||
hostapd_setup_bss(hapd, hapd == iface->bss[0], true);
|
||||
hostapd_ucode_update_interfaces();
|
||||
|
||||
done:
|
||||
ret = 0;
|
||||
|
||||
free:
|
||||
hostapd_config_free(conf);
|
||||
out:
|
||||
return ucv_int64_new(ret);
|
||||
}
|
||||
@@ -178,10 +290,15 @@ uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface;
|
||||
int i, idx;
|
||||
|
||||
if (!hapd || hapd == hapd->iface->bss[0])
|
||||
if (!hapd)
|
||||
return NULL;
|
||||
|
||||
iface = hapd->iface;
|
||||
if (iface->num_bss == 1) {
|
||||
wpa_printf(MSG_ERROR, "trying to delete last bss of an iface: %s\n", hapd->conf->iface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < iface->num_bss; idx++)
|
||||
if (iface->bss[idx] == hapd)
|
||||
break;
|
||||
@@ -191,8 +308,13 @@ uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
|
||||
|
||||
for (i = idx + 1; i < iface->num_bss; i++)
|
||||
iface->bss[i - 1] = iface->bss[i];
|
||||
|
||||
iface->num_bss--;
|
||||
|
||||
iface->bss[0]->interface_added = 0;
|
||||
hostapd_drv_set_first_bss(iface->bss[0]);
|
||||
hapd->interface_added = 1;
|
||||
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hostapd_bss_deinit(hapd);
|
||||
hostapd_remove_iface_bss_conf(iface->conf, hapd->conf);
|
||||
@@ -266,6 +388,58 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_iface_set_bss_order(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
uc_value_t *bss_list = uc_fn_arg(0);
|
||||
struct hostapd_data **new_bss;
|
||||
struct hostapd_bss_config **new_conf;
|
||||
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
||||
if (ucv_type(bss_list) != UC_ARRAY ||
|
||||
ucv_array_length(bss_list) != iface->num_bss)
|
||||
return NULL;
|
||||
|
||||
new_bss = calloc(iface->num_bss, sizeof(*new_bss));
|
||||
new_conf = calloc(iface->num_bss, sizeof(*new_conf));
|
||||
for (size_t i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *bss;
|
||||
|
||||
bss = ucv_resource_data(ucv_array_get(bss_list, i), "hostapd.bss");
|
||||
if (bss->iface != iface)
|
||||
goto free;
|
||||
|
||||
for (size_t k = 0; k < i; k++)
|
||||
if (new_bss[k] == bss)
|
||||
goto free;
|
||||
|
||||
new_bss[i] = bss;
|
||||
new_conf[i] = bss->conf;
|
||||
}
|
||||
|
||||
new_bss[0]->interface_added = 0;
|
||||
for (size_t i = 1; i < iface->num_bss; i++)
|
||||
new_bss[i]->interface_added = 1;
|
||||
|
||||
free(iface->bss);
|
||||
iface->bss = new_bss;
|
||||
|
||||
free(iface->conf->bss);
|
||||
iface->conf->bss = new_conf;
|
||||
iface->conf->num_bss = iface->num_bss;
|
||||
hostapd_drv_set_first_bss(iface->bss[0]);
|
||||
|
||||
return ucv_boolean_new(true);
|
||||
|
||||
free:
|
||||
free(new_bss);
|
||||
free(new_conf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
@@ -297,12 +471,32 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
int i;
|
||||
|
||||
switch (iface->state) {
|
||||
case HAPD_IFACE_ENABLED:
|
||||
case HAPD_IFACE_DISABLED:
|
||||
break;
|
||||
#ifdef CONFIG_ACS
|
||||
case HAPD_IFACE_ACS:
|
||||
acs_cleanup(iface);
|
||||
iface->scan_cb = NULL;
|
||||
/* fallthrough */
|
||||
#endif
|
||||
default:
|
||||
hostapd_disable_iface(iface);
|
||||
break;
|
||||
}
|
||||
|
||||
if (iface->state != HAPD_IFACE_ENABLED)
|
||||
hostapd_disable_iface(iface);
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *hapd = iface->bss[i];
|
||||
|
||||
hostapd_drv_stop_ap(hapd);
|
||||
hapd->started = 0;
|
||||
hapd->beacon_set_done = 0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
@@ -311,67 +505,85 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
|
||||
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
||||
uc_value_t *info = uc_fn_arg(0);
|
||||
struct hostapd_config *conf;
|
||||
bool changed = false;
|
||||
uint64_t intval;
|
||||
int i;
|
||||
|
||||
if (!iface)
|
||||
return NULL;
|
||||
|
||||
if (!info)
|
||||
if (!info) {
|
||||
iface->freq = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ucv_type(info) != UC_OBJECT)
|
||||
return NULL;
|
||||
|
||||
#define UPDATE_VAL(field, name) \
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, name, NULL))) && \
|
||||
!errno && intval != conf->field) do { \
|
||||
conf->field = intval; \
|
||||
changed = true; \
|
||||
} while(0)
|
||||
|
||||
conf = iface->conf;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno)
|
||||
conf->op_class = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno)
|
||||
conf->hw_mode = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno)
|
||||
conf->channel = intval;
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
|
||||
conf->secondary_channel = intval;
|
||||
#ifdef CONFIG_IEEE80211AC
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL))) && !errno) {
|
||||
conf->vht_oper_centr_freq_seg0_idx = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_centr_freq_seg0_idx = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_centr_freq_seg0_idx = intval;
|
||||
#endif
|
||||
}
|
||||
if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL))) && !errno) {
|
||||
conf->vht_oper_centr_freq_seg1_idx = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_centr_freq_seg1_idx = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_centr_freq_seg1_idx = intval;
|
||||
#endif
|
||||
}
|
||||
UPDATE_VAL(op_class, "op_class");
|
||||
UPDATE_VAL(hw_mode, "hw_mode");
|
||||
UPDATE_VAL(channel, "channel");
|
||||
UPDATE_VAL(secondary_channel, "sec_channel");
|
||||
if (!changed &&
|
||||
(iface->bss[0]->beacon_set_done ||
|
||||
iface->state == HAPD_IFACE_DFS))
|
||||
return ucv_boolean_new(true);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL));
|
||||
if (!errno)
|
||||
hostapd_set_oper_centr_freq_seg0_idx(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL));
|
||||
if (!errno)
|
||||
hostapd_set_oper_centr_freq_seg1_idx(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
|
||||
if (!errno) {
|
||||
conf->vht_oper_chwidth = intval;
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
conf->he_oper_chwidth = intval;
|
||||
#endif
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
conf->eht_oper_chwidth = intval;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (!errno)
|
||||
hostapd_set_oper_chwidth(conf, intval);
|
||||
|
||||
intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL));
|
||||
if (!errno)
|
||||
iface->freq = intval;
|
||||
else
|
||||
iface->freq = 0;
|
||||
conf->acs = 0;
|
||||
|
||||
out:
|
||||
if (conf->channel)
|
||||
switch (iface->state) {
|
||||
case HAPD_IFACE_DISABLED:
|
||||
break;
|
||||
case HAPD_IFACE_ENABLED:
|
||||
if (!hostapd_is_dfs_required(iface) ||
|
||||
hostapd_is_dfs_chan_available(iface))
|
||||
break;
|
||||
wpa_printf(MSG_INFO, "DFS CAC required on new channel, restart interface");
|
||||
/* fallthrough */
|
||||
default:
|
||||
hostapd_disable_iface(iface);
|
||||
break;
|
||||
}
|
||||
|
||||
if (conf->channel && !iface->freq)
|
||||
iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel);
|
||||
|
||||
if (iface->state != HAPD_IFACE_ENABLED) {
|
||||
hostapd_enable_iface(iface);
|
||||
return ucv_boolean_new(true);
|
||||
}
|
||||
|
||||
for (i = 0; i < iface->num_bss; i++) {
|
||||
struct hostapd_data *hapd = iface->bss[i];
|
||||
int ret;
|
||||
|
||||
hapd->started = 1;
|
||||
hapd->conf->start_disabled = 0;
|
||||
hostapd_set_freq(hapd, conf->hw_mode, iface->freq,
|
||||
conf->channel,
|
||||
conf->enable_edmg,
|
||||
@@ -436,6 +648,55 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
|
||||
return ucv_boolean_new(!ret);
|
||||
}
|
||||
|
||||
static uc_value_t *
|
||||
uc_hostapd_bss_rename(uc_vm_t *vm, size_t nargs)
|
||||
{
|
||||
struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss");
|
||||
uc_value_t *ifname_arg = uc_fn_arg(0);
|
||||
char prev_ifname[IFNAMSIZ + 1];
|
||||
struct sta_info *sta;
|
||||
const char *ifname;
|
||||
int ret;
|
||||
|
||||
if (!hapd || ucv_type(ifname_arg) != UC_STRING)
|
||||
return NULL;
|
||||
|
||||
os_strlcpy(prev_ifname, hapd->conf->iface, sizeof(prev_ifname));
|
||||
ifname = ucv_string_get(ifname_arg);
|
||||
|
||||
hostapd_ubus_free_bss(hapd);
|
||||
if (interfaces->ctrl_iface_deinit)
|
||||
interfaces->ctrl_iface_deinit(hapd);
|
||||
|
||||
ret = hostapd_drv_if_rename(hapd, WPA_IF_AP_BSS, NULL, ifname);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
char cur_name[IFNAMSIZ + 1], new_name[IFNAMSIZ + 1];
|
||||
|
||||
if (!(sta->flags & WLAN_STA_WDS) || sta->pending_wds_enable)
|
||||
continue;
|
||||
|
||||
snprintf(cur_name, sizeof(cur_name), "%s.sta%d", prev_ifname, sta->aid);
|
||||
snprintf(new_name, sizeof(new_name), "%s.sta%d", ifname, sta->aid);
|
||||
hostapd_drv_if_rename(hapd, WPA_IF_AP_VLAN, cur_name, new_name);
|
||||
}
|
||||
|
||||
if (!strncmp(hapd->conf->ssid.vlan, hapd->conf->iface, sizeof(hapd->conf->ssid.vlan)))
|
||||
os_strlcpy(hapd->conf->ssid.vlan, ifname, sizeof(hapd->conf->ssid.vlan));
|
||||
os_strlcpy(hapd->conf->iface, ifname, sizeof(hapd->conf->iface));
|
||||
hostapd_ubus_add_bss(hapd);
|
||||
|
||||
hostapd_ucode_update_interfaces();
|
||||
out:
|
||||
if (interfaces->ctrl_iface_init)
|
||||
interfaces->ctrl_iface_init(hapd);
|
||||
|
||||
return ret ? NULL : ucv_boolean_new(true);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
||||
{
|
||||
static const uc_function_list_t global_fns[] = {
|
||||
@@ -449,9 +710,11 @@ int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
||||
static const uc_function_list_t bss_fns[] = {
|
||||
{ "ctrl", uc_hostapd_bss_ctrl },
|
||||
{ "set_config", uc_hostapd_bss_set_config },
|
||||
{ "rename", uc_hostapd_bss_rename },
|
||||
{ "delete", uc_hostapd_bss_delete },
|
||||
};
|
||||
static const uc_function_list_t iface_fns[] = {
|
||||
{ "set_bss_order", uc_hostapd_iface_set_bss_order },
|
||||
{ "add_bss", uc_hostapd_iface_add_bss },
|
||||
{ "stop", uc_hostapd_iface_stop },
|
||||
{ "start", uc_hostapd_iface_start },
|
||||
|
||||
@@ -129,7 +129,10 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
|
||||
tmp_channel &= ~((8 << width) - 1);
|
||||
center_idx = tmp_channel + center_ofs + (4 << width) - 1;
|
||||
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx));
|
||||
if (freq_val < 3000)
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(0));
|
||||
else
|
||||
ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx));
|
||||
center_idx = (center_idx - channel) * 5 + freq_val;
|
||||
ucv_object_add(ret, "center_freq1", ucv_int64_new(center_idx));
|
||||
|
||||
@@ -295,9 +298,15 @@ uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx)
|
||||
uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx)
|
||||
{
|
||||
uc_value_t *val = wpa_ucode_registry_get(reg, idx);
|
||||
void **dataptr;
|
||||
|
||||
if (val)
|
||||
ucv_array_set(reg, idx - 1, NULL);
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
ucv_array_set(reg, idx - 1, NULL);
|
||||
dataptr = ucv_resource_dataptr(val, NULL);
|
||||
if (dataptr)
|
||||
*dataptr = NULL;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "utils/common.h"
|
||||
#include "utils/ucode.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "wpa_supplicant_i.h"
|
||||
#include "wps_supplicant.h"
|
||||
#include "bss.h"
|
||||
@@ -211,12 +212,13 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
|
||||
ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
|
||||
if (ie && ie[1] >= 2) {
|
||||
const struct ieee80211_ht_operation *ht_oper;
|
||||
int sec;
|
||||
|
||||
ht_oper = (const void *) (ie + 2);
|
||||
if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
sec = ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
|
||||
if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
||||
sec_chan = 1;
|
||||
else if (ht_oper->ht_param &
|
||||
HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
||||
sec_chan = -1;
|
||||
}
|
||||
|
||||
@@ -224,6 +226,15 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
|
||||
ucv_object_add(ret, "frequency", ucv_int64_new(bss->freq));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MESH
|
||||
if (wpa_s->ifmsh) {
|
||||
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
|
||||
|
||||
ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(ifmsh->conf->secondary_channel));
|
||||
ucv_object_add(ret, "frequency", ucv_int64_new(ifmsh->freq));
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -488,6 +488,7 @@ ${channel:+channel=$channel}
|
||||
${channel_list:+chanlist=$channel_list}
|
||||
${hostapd_noscan:+noscan=1}
|
||||
${tx_burst:+tx_queue_data2_burst=$tx_burst}
|
||||
#num_global_macaddr=$num_global_macaddr
|
||||
$base_cfg
|
||||
|
||||
EOF
|
||||
@@ -528,6 +529,7 @@ mac80211_hostapd_setup_bss() {
|
||||
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
|
||||
@@ -542,57 +544,9 @@ mac80211_get_addr() {
|
||||
|
||||
mac80211_generate_mac() {
|
||||
local phy="$1"
|
||||
local multiple_bssid="$2"
|
||||
local id="${macidx:-0}"
|
||||
|
||||
local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
|
||||
local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
|
||||
|
||||
[ "$mask" = "00:00:00:00:00:00" -a "$multiple_bssid" != 1 ] && {
|
||||
mask="ff:ff:ff:ff:ff:ff";
|
||||
|
||||
[ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt $id ] && {
|
||||
addr="$(mac80211_get_addr "$phy" "$id")"
|
||||
[ -n "$addr" ] && {
|
||||
echo "$addr"
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
|
||||
|
||||
local mask1=$1
|
||||
local mask6=$6
|
||||
|
||||
local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
|
||||
[ "$multiple_bssid" -eq 1 ] && {
|
||||
printf "02:%s:%s:%s:%s:%02x" $b1 $2 $3 $4 $5 $macidx
|
||||
return
|
||||
}
|
||||
macidx=$(($id + 1))
|
||||
|
||||
local use_global=0
|
||||
[ "$id" -gt 0 -a "$macidx" -le "$num_global_macaddr" ] && use_global=1
|
||||
|
||||
[ "$((0x$mask1))" -gt 0 -a "$use_global" -lt 1 ] && {
|
||||
b1="0x$1"
|
||||
[ "$id" -gt 0 ] && \
|
||||
b1=$(($b1 ^ ((($id - !($b1 & 2)) << 2)) | 0x2))
|
||||
printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
|
||||
return
|
||||
}
|
||||
|
||||
[ "$((0x$mask6))" -lt 255 -a "$use_global" -gt 0 ] && {
|
||||
printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
|
||||
return
|
||||
}
|
||||
|
||||
off2=$(( (0x$6 + $id) / 0x100 ))
|
||||
printf "%s:%s:%s:%s:%02x:%02x" \
|
||||
$1 $2 $3 $4 \
|
||||
$(( (0x$5 + $off2) % 0x100 )) \
|
||||
$(( (0x$6 + $id) % 0x100 ))
|
||||
wdev_tool "$phy" get_macaddr id=$id num_global=$num_global_macaddr mbssid=$multiple_bssid
|
||||
}
|
||||
|
||||
find_phy() {
|
||||
@@ -626,11 +580,14 @@ mac80211_prepare_vif() {
|
||||
set_default powersave 0
|
||||
json_add_string _ifname "$ifname"
|
||||
|
||||
default_macaddr=
|
||||
[ -n "$macaddr" ] || {
|
||||
macaddr="$(mac80211_generate_mac $phy $multiple_bssid)"
|
||||
macaddr="$(mac80211_generate_mac $phy)"
|
||||
macidx="$(($macidx + 1))"
|
||||
default_macaddr=1
|
||||
}
|
||||
json_add_string _macaddr "$macaddr"
|
||||
json_add_string _default_macaddr "$default_macaddr"
|
||||
json_select ..
|
||||
|
||||
|
||||
@@ -754,7 +711,7 @@ mac80211_setup_adhoc() {
|
||||
|
||||
json_add_object "$ifname"
|
||||
json_add_string mode adhoc
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
json_add_string ssid "$ssid"
|
||||
json_add_string freq "$freq"
|
||||
json_add_string htmode "$iw_htmode"
|
||||
@@ -780,7 +737,7 @@ mac80211_setup_mesh() {
|
||||
|
||||
json_add_object "$ifname"
|
||||
json_add_string mode mesh
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
json_add_string ssid "$ssid"
|
||||
json_add_string freq "$freq"
|
||||
json_add_string htmode "$iw_htmode"
|
||||
@@ -831,7 +788,6 @@ wpa_supplicant_init_config() {
|
||||
wpa_supplicant_add_interface() {
|
||||
local ifname="$1"
|
||||
local mode="$2"
|
||||
local hostapd_ctrl="$3"
|
||||
local prev
|
||||
|
||||
_wpa_supplicant_common "$ifname"
|
||||
@@ -843,9 +799,8 @@ wpa_supplicant_add_interface() {
|
||||
json_add_string iface "$ifname"
|
||||
json_add_string mode "$mode"
|
||||
json_add_string config "$_config"
|
||||
json_add_string macaddr "$macaddr"
|
||||
[ -n "$default_macaddr" ] || json_add_string macaddr "$macaddr"
|
||||
[ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
|
||||
[ -n "$hostapd_ctrl" ] && json_add_string hostapd_ctrl "$hostapd_ctrl"
|
||||
[ -n "$wds" ] && json_add_boolean 4addr "$wds"
|
||||
json_add_boolean powersave "$powersave"
|
||||
[ "$mode" = "mesh" ] && mac80211_add_mesh_params
|
||||
@@ -920,7 +875,7 @@ mac80211_setup_supplicant() {
|
||||
wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
|
||||
fi
|
||||
|
||||
wpa_supplicant_add_interface "$ifname" "$mode" "$hostapd_ctrl"
|
||||
wpa_supplicant_add_interface "$ifname" "$mode"
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -932,6 +887,7 @@ mac80211_setup_vif() {
|
||||
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
|
||||
@@ -1014,7 +970,7 @@ mac80211_reset_config() {
|
||||
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" '{}'
|
||||
wdev_tool "$phy" set_config '{}'
|
||||
}
|
||||
|
||||
drv_mac80211_setup() {
|
||||
@@ -1116,7 +1072,7 @@ drv_mac80211_setup() {
|
||||
|
||||
mac80211_prepare_iw_htmode
|
||||
active_ifnames=
|
||||
for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif ${multiple_bssid}
|
||||
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"
|
||||
@@ -1125,7 +1081,7 @@ drv_mac80211_setup() {
|
||||
[ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
|
||||
|
||||
json_set_namespace wdev_uc prev
|
||||
wdev_tool "$phy" "$(json_dump)" $active_ifnames
|
||||
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
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 14 Sep 2023 13:17:16 +0200
|
||||
Subject: [PATCH] cfg80211: allow grace period for DFS available after beacon
|
||||
shutdown
|
||||
|
||||
Fixes reconfiguring an AP on a DFS channel in non-ETSI regdomain
|
||||
|
||||
Fixes: b35a51c7dd25 ("cfg80211: Make pre-CAC results valid only for ETSI domain")
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -162,6 +162,8 @@ enum ieee80211_channel_flags {
|
||||
* @dfs_state: current state of this channel. Only relevant if radar is required
|
||||
* on this channel.
|
||||
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
|
||||
+ * @dfs_state_last_available: timestamp (jiffies) of the last time when the
|
||||
+ * channel was available.
|
||||
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
|
||||
*/
|
||||
struct ieee80211_channel {
|
||||
@@ -178,6 +180,7 @@ struct ieee80211_channel {
|
||||
int orig_mag, orig_mpwr;
|
||||
enum nl80211_dfs_state dfs_state;
|
||||
unsigned long dfs_state_entered;
|
||||
+ unsigned long dfs_state_last_available;
|
||||
unsigned int dfs_cac_ms;
|
||||
};
|
||||
|
||||
--- a/net/wireless/ap.c
|
||||
+++ b/net/wireless/ap.c
|
||||
@@ -25,6 +25,8 @@ int __cfg80211_stop_ap(struct cfg80211_r
|
||||
if (!wdev->beacon_interval)
|
||||
return -ENOENT;
|
||||
|
||||
+ cfg80211_update_last_available(wdev->wiphy, &wdev->chandef);
|
||||
+
|
||||
err = rdev_stop_ap(rdev, dev);
|
||||
if (!err) {
|
||||
wdev->conn_owner_nlportid = 0;
|
||||
@@ -35,9 +37,6 @@ int __cfg80211_stop_ap(struct cfg80211_r
|
||||
if (notify)
|
||||
nl80211_send_ap_stopped(wdev);
|
||||
|
||||
- /* Should we apply the grace period during beaconing interface
|
||||
- * shutdown also?
|
||||
- */
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
}
|
||||
|
||||
--- a/net/wireless/chan.c
|
||||
+++ b/net/wireless/chan.c
|
||||
@@ -411,6 +411,8 @@ static void cfg80211_set_chans_dfs_state
|
||||
|
||||
c->dfs_state = dfs_state;
|
||||
c->dfs_state_entered = jiffies;
|
||||
+ if (dfs_state == NL80211_DFS_AVAILABLE)
|
||||
+ c->dfs_state_last_available = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,6 +771,49 @@ static bool cfg80211_get_chans_dfs_avail
|
||||
return true;
|
||||
}
|
||||
|
||||
+static void
|
||||
+__cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ u32 center_freq,
|
||||
+ u32 bandwidth)
|
||||
+{
|
||||
+ struct ieee80211_channel *c;
|
||||
+ u32 freq, start_freq, end_freq;
|
||||
+
|
||||
+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||
+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||
+
|
||||
+ /*
|
||||
+ * Check entire range of channels for the bandwidth.
|
||||
+ * If any channel in between is disabled or has not
|
||||
+ * had gone through CAC return false
|
||||
+ */
|
||||
+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
|
||||
+ c = ieee80211_get_channel_khz(wiphy, freq);
|
||||
+ if (!c)
|
||||
+ return;
|
||||
+
|
||||
+ c->dfs_state_last_available = jiffies;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef)
|
||||
+{
|
||||
+ int width;
|
||||
+
|
||||
+ width = cfg80211_chandef_get_width(chandef);
|
||||
+ if (width < 0)
|
||||
+ return;
|
||||
+
|
||||
+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1),
|
||||
+ width);
|
||||
+ if (chandef->width != NL80211_CHAN_WIDTH_80P80)
|
||||
+ return;
|
||||
+
|
||||
+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2),
|
||||
+ width);
|
||||
+}
|
||||
+
|
||||
static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
--- a/net/wireless/core.h
|
||||
+++ b/net/wireless/core.h
|
||||
@@ -483,6 +483,8 @@ void cfg80211_set_dfs_state(struct wiphy
|
||||
enum nl80211_dfs_state dfs_state);
|
||||
|
||||
void cfg80211_dfs_channels_update_work(struct work_struct *work);
|
||||
+void cfg80211_update_last_available(struct wiphy *wiphy,
|
||||
+ const struct cfg80211_chan_def *chandef);
|
||||
|
||||
unsigned int
|
||||
cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -858,6 +858,8 @@ void cfg80211_dfs_channels_update_work(s
|
||||
if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
|
||||
time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
|
||||
radar_event = NL80211_RADAR_NOP_FINISHED;
|
||||
+ timeout = c->dfs_state_entered +
|
||||
+ msecs_to_jiffies(time_dfs_update);
|
||||
} else {
|
||||
if (regulatory_pre_cac_allowed(wiphy) ||
|
||||
cfg80211_any_wiphy_oper_chan(wiphy, c))
|
||||
@@ -865,11 +867,10 @@ void cfg80211_dfs_channels_update_work(s
|
||||
|
||||
time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
|
||||
radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
|
||||
+ timeout = c->dfs_state_last_available +
|
||||
+ msecs_to_jiffies(time_dfs_update);
|
||||
}
|
||||
|
||||
- timeout = c->dfs_state_entered +
|
||||
- msecs_to_jiffies(time_dfs_update);
|
||||
-
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
c->dfs_state = NL80211_DFS_USABLE;
|
||||
c->dfs_state_entered = jiffies;
|
||||
@@ -0,0 +1,587 @@
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -557,8 +557,8 @@ config_parse_wireless_device(struct uci_
|
||||
wireless_device_create(drv, s->e.name, b.head);
|
||||
}
|
||||
|
||||
-static struct wireless_interface*
|
||||
-config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
|
||||
+static void
|
||||
+config_parse_wireless_vlan(struct wireless_interface *vif, struct uci_section *s)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@@ -566,12 +566,12 @@ config_parse_wireless_interface(struct w
|
||||
sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
- uci_to_blob(&b, s, wdev->drv->interface.config);
|
||||
- return wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
||||
+ uci_to_blob(&b, s, vif->wdev->drv->vlan.config);
|
||||
+ wireless_vlan_create(vif, b.head, s->anonymous ? name : s->e.name);
|
||||
}
|
||||
|
||||
static void
|
||||
-config_parse_wireless_vlan(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
||||
+config_parse_wireless_station(struct wireless_interface *vif, struct uci_section *s)
|
||||
{
|
||||
char *name;
|
||||
|
||||
@@ -579,21 +579,62 @@ config_parse_wireless_vlan(struct wirele
|
||||
sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
- uci_to_blob(&b, s, wdev->drv->vlan.config);
|
||||
- wireless_vlan_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
||||
+ uci_to_blob(&b, s, vif->wdev->drv->station.config);
|
||||
+ wireless_station_create(vif, b.head, s->anonymous ? name : s->e.name);
|
||||
}
|
||||
|
||||
static void
|
||||
-config_parse_wireless_station(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
||||
+config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
|
||||
{
|
||||
+ struct wireless_interface *vif;
|
||||
+ struct uci_element *f;
|
||||
char *name;
|
||||
|
||||
name = alloca(strlen(s->type) + 16);
|
||||
sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
- uci_to_blob(&b, s, wdev->drv->station.config);
|
||||
- wireless_station_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
||||
+ uci_to_blob(&b, s, wdev->drv->interface.config);
|
||||
+ vif = wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
||||
+ if (!vif)
|
||||
+ return;
|
||||
+
|
||||
+ vif->vlan_idx = vif->sta_idx = 0;
|
||||
+ vlist_update(&vif->vlans);
|
||||
+ vlist_update(&vif->stations);
|
||||
+
|
||||
+ if (s->anonymous)
|
||||
+ goto out;
|
||||
+
|
||||
+ uci_foreach_element(&uci_wireless->sections, f) {
|
||||
+ struct uci_section *cur = uci_to_section(f);
|
||||
+ const char *vif_name;
|
||||
+
|
||||
+ if (strcmp(cur->type, "wifi-vlan") != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
|
||||
+ if (vif_name && strcmp(s->e.name, vif_name))
|
||||
+ continue;
|
||||
+ config_parse_wireless_vlan(vif, cur);
|
||||
+ }
|
||||
+
|
||||
+ uci_foreach_element(&uci_wireless->sections, f) {
|
||||
+ struct uci_section *cur = uci_to_section(f);
|
||||
+ const char *vif_name;
|
||||
+
|
||||
+ if (strcmp(cur->type, "wifi-station") != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
|
||||
+ if (vif_name && strcmp(s->e.name, vif_name))
|
||||
+ continue;
|
||||
+ config_parse_wireless_station(vif, cur);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ vlist_flush(&vif->vlans);
|
||||
+ vlist_flush(&vif->stations);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -623,16 +664,10 @@ config_init_wireless(void)
|
||||
vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
wdev->vif_idx = 0;
|
||||
vlist_update(&wdev->interfaces);
|
||||
- wdev->vlan_idx = 0;
|
||||
- vlist_update(&wdev->vlans);
|
||||
- wdev->sta_idx = 0;
|
||||
- vlist_update(&wdev->stations);
|
||||
}
|
||||
|
||||
uci_foreach_element(&uci_wireless->sections, e) {
|
||||
struct uci_section *s = uci_to_section(e);
|
||||
- struct wireless_interface *vif;
|
||||
- struct uci_element *f;
|
||||
|
||||
if (strcmp(s->type, "wifi-iface") != 0)
|
||||
continue;
|
||||
@@ -647,42 +682,11 @@ config_init_wireless(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
- vif = config_parse_wireless_interface(wdev, s);
|
||||
-
|
||||
- if (!vif || s->anonymous)
|
||||
- continue;
|
||||
- uci_foreach_element(&uci_wireless->sections, f) {
|
||||
- struct uci_section *s = uci_to_section(f);
|
||||
- const char *vif_name;
|
||||
-
|
||||
- if (strcmp(s->type, "wifi-vlan") != 0)
|
||||
- continue;
|
||||
-
|
||||
- vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
||||
- if (vif_name && strcmp(e->name, vif_name))
|
||||
- continue;
|
||||
- config_parse_wireless_vlan(wdev, vif->name, s);
|
||||
- }
|
||||
-
|
||||
- uci_foreach_element(&uci_wireless->sections, f) {
|
||||
- struct uci_section *s = uci_to_section(f);
|
||||
- const char *vif_name;
|
||||
-
|
||||
- if (strcmp(s->type, "wifi-station") != 0)
|
||||
- continue;
|
||||
-
|
||||
- vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
||||
- if (vif_name && strcmp(e->name, vif_name))
|
||||
- continue;
|
||||
- config_parse_wireless_station(wdev, vif->name, s);
|
||||
- }
|
||||
+ config_parse_wireless_interface(wdev, s);
|
||||
}
|
||||
|
||||
- vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
+ vlist_for_each_element(&wireless_devices, wdev, node)
|
||||
vlist_flush(&wdev->interfaces);
|
||||
- vlist_flush(&wdev->vlans);
|
||||
- vlist_flush(&wdev->stations);
|
||||
- }
|
||||
}
|
||||
|
||||
|
||||
--- a/scripts/netifd-wireless.sh
|
||||
+++ b/scripts/netifd-wireless.sh
|
||||
@@ -108,14 +108,16 @@ _wdev_wrapper() {
|
||||
}
|
||||
|
||||
_wdev_notify_init() {
|
||||
- local command="$1"
|
||||
- local name="$2"
|
||||
- local value="$3"
|
||||
+ local command="$1"; shift;
|
||||
|
||||
json_init
|
||||
json_add_int "command" "$command"
|
||||
json_add_string "device" "$__netifd_device"
|
||||
- [ -n "$name" -a -n "$value" ] && json_add_string "$name" "$value"
|
||||
+ while [ -n "$1" ]; do
|
||||
+ local name="$1"; shift
|
||||
+ local value="$1"; shift
|
||||
+ json_add_string "$name" "$value"
|
||||
+ done
|
||||
json_add_object "data"
|
||||
}
|
||||
|
||||
@@ -151,7 +153,7 @@ _wireless_add_vlan() {
|
||||
local name="$1"; shift
|
||||
local ifname="$1"; shift
|
||||
|
||||
- _wdev_notify_init $CMD_SET_DATA "vlan" "$name"
|
||||
+ _wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
|
||||
json_add_string "ifname" "$ifname"
|
||||
_wdev_add_variables "$@"
|
||||
_wdev_notify
|
||||
@@ -333,6 +335,7 @@ for_each_interface() {
|
||||
continue
|
||||
}
|
||||
fi
|
||||
+ __cur_interface="$_w_iface"
|
||||
"$@" "$_w_iface"
|
||||
json_select ..
|
||||
done
|
||||
--- a/wireless.c
|
||||
+++ b/wireless.c
|
||||
@@ -205,9 +205,7 @@ prepare_config(struct wireless_device *w
|
||||
blobmsg_add_blob(&b, vif->data);
|
||||
|
||||
j = blobmsg_open_table(&b, "vlans");
|
||||
- vlist_for_each_element(&wdev->vlans, vlan, node) {
|
||||
- if (strcmp(vlan->vif, vif->name))
|
||||
- continue;
|
||||
+ vlist_for_each_element(&vif->vlans, vlan, node) {
|
||||
k = blobmsg_open_table(&b, vlan->name);
|
||||
vif_config_add_bridge(&b, vlan->network, up);
|
||||
put_container(&b, vlan->config, "config");
|
||||
@@ -218,9 +216,7 @@ prepare_config(struct wireless_device *w
|
||||
blobmsg_close_table(&b, j);
|
||||
|
||||
j = blobmsg_open_table(&b, "stas");
|
||||
- vlist_for_each_element(&wdev->stations, sta, node) {
|
||||
- if (strcmp(sta->vif, vif->name))
|
||||
- continue;
|
||||
+ vlist_for_each_element(&vif->stations, sta, node) {
|
||||
k = blobmsg_open_table(&b, sta->name);
|
||||
put_container(&b, sta->config, "config");
|
||||
if (sta->data)
|
||||
@@ -311,15 +307,15 @@ wireless_device_free_state(struct wirele
|
||||
free(vif->data);
|
||||
vif->data = NULL;
|
||||
vif->ifname = NULL;
|
||||
- }
|
||||
- vlist_for_each_element(&wdev->vlans, vlan, node) {
|
||||
- free(vlan->data);
|
||||
- vlan->data = NULL;
|
||||
- vlan->ifname = NULL;
|
||||
- }
|
||||
- vlist_for_each_element(&wdev->stations, sta, node) {
|
||||
- free(sta->data);
|
||||
- sta->data = NULL;
|
||||
+ vlist_for_each_element(&vif->vlans, vlan, node) {
|
||||
+ free(vlan->data);
|
||||
+ vlan->data = NULL;
|
||||
+ vlan->ifname = NULL;
|
||||
+ }
|
||||
+ vlist_for_each_element(&vif->stations, sta, node) {
|
||||
+ free(sta->data);
|
||||
+ sta->data = NULL;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,8 +506,6 @@ wireless_device_free(struct wireless_dev
|
||||
{
|
||||
wireless_handler_stop(wdev);
|
||||
vlist_flush_all(&wdev->interfaces);
|
||||
- vlist_flush_all(&wdev->vlans);
|
||||
- vlist_flush_all(&wdev->stations);
|
||||
avl_delete(&wireless_devices.avl, &wdev->node.avl);
|
||||
free(wdev->config);
|
||||
free(wdev->prev_config);
|
||||
@@ -547,11 +541,12 @@ wireless_device_mark_down(struct wireles
|
||||
|
||||
netifd_log_message(L_NOTICE, "Wireless device '%s' is now down\n", wdev->name);
|
||||
|
||||
- vlist_for_each_element(&wdev->vlans, vlan, node)
|
||||
- wireless_vlan_handle_link(vlan, false);
|
||||
|
||||
- vlist_for_each_element(&wdev->interfaces, vif, node)
|
||||
+ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
wireless_interface_handle_link(vif, NULL, false);
|
||||
+ vlist_for_each_element(&vif->vlans, vlan, node)
|
||||
+ wireless_vlan_handle_link(vlan, false);
|
||||
+ }
|
||||
|
||||
wireless_process_kill_all(wdev, SIGTERM, true);
|
||||
|
||||
@@ -623,10 +618,11 @@ wireless_device_mark_up(struct wireless_
|
||||
netifd_log_message(L_NOTICE, "Wireless device '%s' is now up\n", wdev->name);
|
||||
wdev->retry = WIRELESS_SETUP_RETRY;
|
||||
wdev->state = IFS_UP;
|
||||
- vlist_for_each_element(&wdev->interfaces, vif, node)
|
||||
+ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
wireless_interface_handle_link(vif, NULL, true);
|
||||
- vlist_for_each_element(&wdev->vlans, vlan, node)
|
||||
- wireless_vlan_handle_link(vlan, true);
|
||||
+ vlist_for_each_element(&vif->vlans, vlan, node)
|
||||
+ wireless_vlan_handle_link(vlan, true);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -848,6 +844,16 @@ wireless_interface_init_config(struct wi
|
||||
vif->multicast_to_unicast = cur ? blobmsg_get_bool(cur) : -1;
|
||||
}
|
||||
|
||||
+static void
|
||||
+vif_free(struct wireless_interface *vif)
|
||||
+{
|
||||
+ vlist_flush_all(&vif->vlans);
|
||||
+ vlist_flush_all(&vif->stations);
|
||||
+ free((void *) vif->section);
|
||||
+ free(vif->config);
|
||||
+ free(vif);
|
||||
+}
|
||||
+
|
||||
/* vlist update call for wireless interface list */
|
||||
static void
|
||||
vif_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
@@ -884,9 +890,7 @@ vif_update(struct vlist_tree *tree, stru
|
||||
} else if (vif_old) {
|
||||
D(WIRELESS, "Delete wireless interface %s on device %s\n", vif_old->name, wdev->name);
|
||||
wireless_interface_handle_link(vif_old, NULL, false);
|
||||
- free((void *) vif_old->section);
|
||||
- free(vif_old->config);
|
||||
- free(vif_old);
|
||||
+ vif_free(vif_old);
|
||||
}
|
||||
|
||||
wdev->config_update = true;
|
||||
@@ -921,14 +925,10 @@ static void
|
||||
vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
struct vlist_node *node_old)
|
||||
{
|
||||
- struct wireless_vlan *vlan_old = container_of(node_old, struct wireless_vlan, node);
|
||||
- struct wireless_vlan *vlan_new = container_of(node_new, struct wireless_vlan, node);
|
||||
- struct wireless_device *wdev;
|
||||
-
|
||||
- if (vlan_old)
|
||||
- wdev = vlan_old->wdev;
|
||||
- else
|
||||
- wdev = vlan_new->wdev;
|
||||
+ struct wireless_vlan *vlan_old = container_of_safe(node_old, struct wireless_vlan, node);
|
||||
+ struct wireless_vlan *vlan_new = container_of_safe(node_new, struct wireless_vlan, node);
|
||||
+ struct wireless_interface *vif = container_of(tree, struct wireless_interface, vlans);
|
||||
+ struct wireless_device *wdev = vif->wdev;
|
||||
|
||||
if (vlan_old && vlan_new) {
|
||||
free((void *) vlan_old->section);
|
||||
@@ -951,7 +951,7 @@ vlan_update(struct vlist_tree *tree, str
|
||||
vlan_new->config = blob_memdup(vlan_new->config);
|
||||
wireless_vlan_init_config(vlan_new);
|
||||
} else if (vlan_old) {
|
||||
- D(WIRELESS, "Delete wireless interface %s on device %s\n", vlan_old->name, wdev->name);
|
||||
+ D(WIRELESS, "Delete wireless vlan %s on device %s\n", vlan_old->name, wdev->name);
|
||||
wireless_vlan_handle_link(vlan_old, false);
|
||||
free((void *) vlan_old->section);
|
||||
free(vlan_old->config);
|
||||
@@ -966,14 +966,10 @@ static void
|
||||
station_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
struct vlist_node *node_old)
|
||||
{
|
||||
- struct wireless_station *sta_old = container_of(node_old, struct wireless_station, node);
|
||||
- struct wireless_station *sta_new = container_of(node_new, struct wireless_station, node);
|
||||
- struct wireless_device *wdev;
|
||||
-
|
||||
- if (sta_old)
|
||||
- wdev = sta_old->wdev;
|
||||
- else
|
||||
- wdev = sta_new->wdev;
|
||||
+ struct wireless_station *sta_old = container_of_safe(node_old, struct wireless_station, node);
|
||||
+ struct wireless_station *sta_new = container_of_safe(node_new, struct wireless_station, node);
|
||||
+ struct wireless_interface *vif = container_of(tree, struct wireless_interface, stations);
|
||||
+ struct wireless_device *wdev = vif->wdev;
|
||||
|
||||
if (sta_old && sta_new) {
|
||||
free((void *) sta_old->section);
|
||||
@@ -1088,10 +1084,6 @@ wireless_device_create(struct wireless_d
|
||||
INIT_LIST_HEAD(&wdev->script_proc);
|
||||
vlist_init(&wdev->interfaces, avl_strcmp, vif_update);
|
||||
wdev->interfaces.keep_old = true;
|
||||
- vlist_init(&wdev->vlans, avl_strcmp, vlan_update);
|
||||
- wdev->vlans.keep_old = true;
|
||||
- vlist_init(&wdev->stations, avl_strcmp, station_update);
|
||||
- wdev->stations.keep_old = true;
|
||||
|
||||
wdev->timeout.cb = wireless_device_setup_timeout;
|
||||
wdev->script_task.cb = wireless_device_script_task_cb;
|
||||
@@ -1108,12 +1100,12 @@ wireless_device_create(struct wireless_d
|
||||
|
||||
/* creates a wireless station object. Called by config */
|
||||
void
|
||||
-wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
||||
+wireless_station_create(struct wireless_interface *vif, struct blob_attr *data, const char *section)
|
||||
{
|
||||
struct wireless_station *sta;
|
||||
struct blob_attr *tb[__STA_ATTR_MAX];
|
||||
struct blob_attr *cur;
|
||||
- char *name_buf, *vif_buf;
|
||||
+ char *name_buf;
|
||||
char name[8];
|
||||
|
||||
blobmsg_parse(sta_policy, __STA_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
||||
@@ -1122,18 +1114,15 @@ wireless_station_create(struct wireless_
|
||||
if (cur && blobmsg_get_bool(cur))
|
||||
return;
|
||||
|
||||
- sprintf(name, "%d", wdev->sta_idx++);
|
||||
+ sprintf(name, "%d", vif->sta_idx++);
|
||||
|
||||
sta = calloc_a(sizeof(*sta),
|
||||
- &name_buf, strlen(name) + 1,
|
||||
- &vif_buf, strlen(vif) + 1);
|
||||
+ &name_buf, strlen(name) + 1);
|
||||
sta->name = strcpy(name_buf, name);
|
||||
- sta->vif = strcpy(vif_buf, vif);
|
||||
- sta->wdev = wdev;
|
||||
sta->config = data;
|
||||
sta->section = section;
|
||||
|
||||
- vlist_add(&wdev->stations, &sta->node, sta->name);
|
||||
+ vlist_add(&vif->stations, &sta->node, sta->name);
|
||||
}
|
||||
|
||||
/* ubus callback network.wireless.status, runs for every interface, encode the station */
|
||||
@@ -1151,12 +1140,12 @@ wireless_station_status(struct wireless_
|
||||
|
||||
/* create a vlan object. Called by config */
|
||||
void
|
||||
-wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
||||
+wireless_vlan_create(struct wireless_interface *vif, struct blob_attr *data, const char *section)
|
||||
{
|
||||
struct wireless_vlan *vlan;
|
||||
struct blob_attr *tb[__VLAN_ATTR_MAX];
|
||||
struct blob_attr *cur;
|
||||
- char *name_buf, *vif_buf;
|
||||
+ char *name_buf;
|
||||
char name[8];
|
||||
|
||||
blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
||||
@@ -1165,19 +1154,14 @@ wireless_vlan_create(struct wireless_dev
|
||||
if (cur && blobmsg_get_bool(cur))
|
||||
return;
|
||||
|
||||
- sprintf(name, "%d", wdev->vlan_idx++);
|
||||
+ sprintf(name, "%d", vif->vlan_idx++);
|
||||
|
||||
- vlan = calloc_a(sizeof(*vlan),
|
||||
- &name_buf, strlen(name) + 1,
|
||||
- &vif_buf, strlen(vif) + 1);
|
||||
+ vlan = calloc_a(sizeof(*vlan), &name_buf, strlen(name) + 1);
|
||||
vlan->name = strcpy(name_buf, name);
|
||||
- vlan->vif = strcpy(vif_buf, vif);
|
||||
- vlan->wdev = wdev;
|
||||
vlan->config = data;
|
||||
vlan->section = section;
|
||||
- vlan->isolate = false;
|
||||
|
||||
- vlist_add(&wdev->vlans, &vlan->node, vlan->name);
|
||||
+ vlist_add(&vif->vlans, &vlan->node, vlan->name);
|
||||
}
|
||||
|
||||
/* ubus callback network.wireless.status, runs for every interface, encode the vlan informations */
|
||||
@@ -1220,6 +1204,12 @@ struct wireless_interface* wireless_inte
|
||||
vif->section = section;
|
||||
vif->isolate = false;
|
||||
|
||||
+ vlist_init(&vif->vlans, avl_strcmp, vlan_update);
|
||||
+ vif->vlans.keep_old = true;
|
||||
+
|
||||
+ vlist_init(&vif->stations, avl_strcmp, station_update);
|
||||
+ vif->stations.keep_old = true;
|
||||
+
|
||||
vlist_add(&wdev->interfaces, &vif->node, vif->name);
|
||||
|
||||
return vlist_find(&wdev->interfaces, name, vif, node);
|
||||
@@ -1240,14 +1230,12 @@ wireless_interface_status(struct wireles
|
||||
blobmsg_add_string(b, "ifname", iface->ifname);
|
||||
put_container(b, iface->config, "config");
|
||||
j = blobmsg_open_array(b, "vlans");
|
||||
- vlist_for_each_element(&iface->wdev->vlans, vlan, node)
|
||||
- if (!strcmp(iface->name, vlan->vif))
|
||||
- wireless_vlan_status(vlan, b);
|
||||
+ vlist_for_each_element(&iface->vlans, vlan, node)
|
||||
+ wireless_vlan_status(vlan, b);
|
||||
blobmsg_close_array(b, j);
|
||||
j = blobmsg_open_array(b, "stations");
|
||||
- vlist_for_each_element(&iface->wdev->stations, sta, node)
|
||||
- if (!strcmp(iface->name, sta->vif))
|
||||
- wireless_station_status(sta, b);
|
||||
+ vlist_for_each_element(&iface->stations, sta, node)
|
||||
+ wireless_station_status(sta, b);
|
||||
blobmsg_close_array(b, j);
|
||||
blobmsg_close_table(b, i);
|
||||
}
|
||||
@@ -1496,7 +1484,9 @@ wireless_device_notify(struct wireless_d
|
||||
}
|
||||
|
||||
if ((cur = tb[NOTIFY_ATTR_VLAN]) != NULL) {
|
||||
- vlan = vlist_find(&wdev->vlans, blobmsg_data(cur), vlan, node);
|
||||
+ if (!vif)
|
||||
+ return UBUS_STATUS_NOT_FOUND;
|
||||
+ vlan = vlist_find(&vif->vlans, blobmsg_data(cur), vlan, node);
|
||||
if (!vlan)
|
||||
return UBUS_STATUS_NOT_FOUND;
|
||||
}
|
||||
@@ -1516,19 +1506,19 @@ wireless_device_notify(struct wireless_d
|
||||
wireless_device_mark_up(wdev);
|
||||
break;
|
||||
case NOTIFY_CMD_SET_DATA:
|
||||
- if (vif)
|
||||
- pdata = &vif->data;
|
||||
- else if (vlan)
|
||||
+ if (vlan)
|
||||
pdata = &vlan->data;
|
||||
+ else if (vif)
|
||||
+ pdata = &vif->data;
|
||||
else
|
||||
pdata = &wdev->data;
|
||||
|
||||
free(*pdata);
|
||||
*pdata = blob_memdup(cur);
|
||||
- if (vif)
|
||||
- wireless_interface_set_data(vif);
|
||||
- else if (vlan)
|
||||
+ if (vlan)
|
||||
wireless_vlan_set_data(vlan);
|
||||
+ else if (vif)
|
||||
+ wireless_interface_set_data(vif);
|
||||
break;
|
||||
case NOTIFY_CMD_PROCESS_ADD:
|
||||
return wireless_device_add_process(wdev, cur);
|
||||
--- a/wireless.h
|
||||
+++ b/wireless.h
|
||||
@@ -44,8 +44,6 @@ struct wireless_device {
|
||||
|
||||
struct wireless_driver *drv;
|
||||
struct vlist_tree interfaces;
|
||||
- struct vlist_tree vlans;
|
||||
- struct vlist_tree stations;
|
||||
char *name;
|
||||
|
||||
struct netifd_process script_task;
|
||||
@@ -73,8 +71,6 @@ struct wireless_device {
|
||||
int retry;
|
||||
|
||||
int vif_idx;
|
||||
- int vlan_idx;
|
||||
- int sta_idx;
|
||||
};
|
||||
|
||||
struct wireless_interface {
|
||||
@@ -82,6 +78,8 @@ struct wireless_interface {
|
||||
const char *section;
|
||||
char *name;
|
||||
|
||||
+ struct vlist_tree vlans;
|
||||
+ struct vlist_tree stations;
|
||||
struct wireless_device *wdev;
|
||||
|
||||
struct blob_attr *config;
|
||||
@@ -94,6 +92,8 @@ struct wireless_interface {
|
||||
bool isolate;
|
||||
bool ap_mode;
|
||||
int multicast_to_unicast;
|
||||
+ int vlan_idx;
|
||||
+ int sta_idx;
|
||||
};
|
||||
|
||||
struct wireless_vlan {
|
||||
@@ -101,9 +101,6 @@ struct wireless_vlan {
|
||||
const char *section;
|
||||
char *name;
|
||||
|
||||
- struct wireless_device *wdev;
|
||||
- char *vif;
|
||||
-
|
||||
struct blob_attr *config;
|
||||
struct blob_attr *data;
|
||||
|
||||
@@ -119,9 +116,6 @@ struct wireless_station {
|
||||
const char *section;
|
||||
char *name;
|
||||
|
||||
- struct wireless_device *wdev;
|
||||
- char *vif;
|
||||
-
|
||||
struct blob_attr *config;
|
||||
struct blob_attr *data;
|
||||
};
|
||||
@@ -143,8 +137,8 @@ void wireless_device_reconf(struct wirel
|
||||
void wireless_device_status(struct wireless_device *wdev, struct blob_buf *b);
|
||||
void wireless_device_get_validate(struct wireless_device *wdev, struct blob_buf *b);
|
||||
struct wireless_interface* wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
||||
-void wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
||||
-void wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
||||
+void wireless_vlan_create(struct wireless_interface *vif, struct blob_attr *data, const char *section);
|
||||
+void wireless_station_create(struct wireless_interface *vif, struct blob_attr *data, const char *section);
|
||||
int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
||||
struct ubus_request_data *req);
|
||||
|
||||
285
patches/backports/0060-netif-dynamic-iface.patch
Normal file
285
patches/backports/0060-netif-dynamic-iface.patch
Normal file
@@ -0,0 +1,285 @@
|
||||
From 4e4128e44fcb6c0f444e4aa481eb8941f47a801a Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 15 Sep 2023 20:47:10 +0200
|
||||
Subject: [PATCH] netifd: add support for enabling/disabling wifi interfaces
|
||||
via ifup/ifdown
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
package/network/config/netifd/files/sbin/ifup | 33 ---
|
||||
.../patches/410-wireless_network_state.patch | 194 ++++++++++++++++++
|
||||
2 files changed, 194 insertions(+), 33 deletions(-)
|
||||
create mode 100644 package/network/config/netifd/patches/410-wireless_network_state.patch
|
||||
|
||||
diff --git a/package/network/config/netifd/files/sbin/ifup b/package/network/config/netifd/files/sbin/ifup
|
||||
index 15be535bbfc9..fbf2fd80c7ea 100755
|
||||
--- a/package/network/config/netifd/files/sbin/ifup
|
||||
+++ b/package/network/config/netifd/files/sbin/ifup
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
ifup_all=
|
||||
-setup_wifi=
|
||||
|
||||
if_call() {
|
||||
local interface="$1"
|
||||
@@ -14,7 +13,6 @@ case "$0" in
|
||||
*ifdown) modes=down;;
|
||||
*ifup)
|
||||
modes="down up"
|
||||
- setup_wifi=1
|
||||
;;
|
||||
*) echo "Invalid command: $0";;
|
||||
esac
|
||||
@@ -25,10 +23,6 @@ while :; do
|
||||
ifup_all=1
|
||||
shift
|
||||
;;
|
||||
- -w)
|
||||
- setup_wifi=
|
||||
- shift
|
||||
- ;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
@@ -40,7 +34,6 @@ if [ -n "$ifup_all" ]; then
|
||||
for interface in $(ubus -S list 'network.interface.*'); do
|
||||
if_call "${interface##network.interface.}"
|
||||
done
|
||||
- [ -n "$setup_wifi" ] && /sbin/wifi up
|
||||
exit
|
||||
else
|
||||
ubus -S list "network.interface.$1" > /dev/null || {
|
||||
@@ -49,29 +42,3 @@ else
|
||||
}
|
||||
if_call "$1"
|
||||
fi
|
||||
-
|
||||
-if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
|
||||
- . /lib/functions.sh
|
||||
-
|
||||
- find_related_radios() {
|
||||
- local wdev wnet
|
||||
- config_get wdev "$1" device
|
||||
- config_get wnet "$1" network
|
||||
-
|
||||
- if [ -n "$wdev" ]; then
|
||||
- for wnet in $wnet; do
|
||||
- if [ "$wnet" = "$network" ]; then
|
||||
- append radio_devs "$wdev" "$N"
|
||||
- fi
|
||||
- done
|
||||
- fi
|
||||
- }
|
||||
-
|
||||
- network="$1"
|
||||
- config_load wireless
|
||||
- config_foreach find_related_radios wifi-iface
|
||||
-
|
||||
- for dev in $(echo "$radio_devs" | sort -u); do
|
||||
- /sbin/wifi up "$dev"
|
||||
- done
|
||||
-fi
|
||||
diff --git a/package/network/config/netifd/patches/410-wireless_network_state.patch b/package/network/config/netifd/patches/410-wireless_network_state.patch
|
||||
new file mode 100644
|
||||
index 000000000000..4e9b905190b6
|
||||
--- /dev/null
|
||||
+++ b/package/network/config/netifd/patches/410-wireless_network_state.patch
|
||||
@@ -0,0 +1,194 @@
|
||||
+--- a/config.c
|
||||
++++ b/config.c
|
||||
+@@ -784,7 +784,7 @@ config_init_all(void)
|
||||
+ vlist_flush(&interfaces);
|
||||
+ interface_refresh_assignments(false);
|
||||
+ interface_start_pending();
|
||||
+- wireless_start_pending();
|
||||
++ wireless_start_pending(0);
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+--- a/interface.c
|
||||
++++ b/interface.c
|
||||
+@@ -25,6 +25,7 @@
|
||||
+ #include "ubus.h"
|
||||
+ #include "config.h"
|
||||
+ #include "system.h"
|
||||
++#include "wireless.h"
|
||||
+
|
||||
+ struct vlist_tree interfaces;
|
||||
+ static LIST_HEAD(iface_all_users);
|
||||
+@@ -1125,6 +1126,7 @@ interface_set_up(struct interface *iface
|
||||
+ const char *error = NULL;
|
||||
+
|
||||
+ iface->autostart = true;
|
||||
++ wireless_check_network_enabled();
|
||||
+
|
||||
+ if (iface->state != IFS_DOWN)
|
||||
+ return;
|
||||
+@@ -1157,6 +1159,7 @@ interface_set_down(struct interface *ifa
|
||||
+ __interface_set_down(iface, false);
|
||||
+ } else {
|
||||
+ iface->autostart = false;
|
||||
++ wireless_check_network_enabled();
|
||||
+ __interface_set_down(iface, false);
|
||||
+ }
|
||||
+ }
|
||||
+--- a/wireless.c
|
||||
++++ b/wireless.c
|
||||
+@@ -198,6 +198,9 @@ prepare_config(struct wireless_device *w
|
||||
+
|
||||
+ l = blobmsg_open_table(&b, "interfaces");
|
||||
+ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
++ if (vif->disabled)
|
||||
++ continue;
|
||||
++
|
||||
+ i = blobmsg_open_table(&b, vif->name);
|
||||
+ vif_config_add_bridge(&b, vif->network, up);
|
||||
+ put_container(&b, vif->config, "config");
|
||||
+@@ -438,6 +441,8 @@ wireless_device_run_handler(struct wirel
|
||||
+ wdev->prev_config = NULL;
|
||||
+ } else {
|
||||
+ prepare_config(wdev, &b, up);
|
||||
++ free(wdev->prev_config);
|
||||
++ wdev->prev_config = up ? blob_memdup(b.head) : NULL;
|
||||
+ config = blobmsg_format_json(b.head, true);
|
||||
+ }
|
||||
+
|
||||
+@@ -495,8 +500,6 @@ __wireless_device_set_up(struct wireless
|
||||
+ if ((!force && wdev->state != IFS_DOWN) || config_init)
|
||||
+ return;
|
||||
+
|
||||
+- free(wdev->prev_config);
|
||||
+- wdev->prev_config = NULL;
|
||||
+ wdev->state = IFS_SETUP;
|
||||
+ wireless_device_run_handler(wdev, true);
|
||||
+ }
|
||||
+@@ -690,16 +693,6 @@ wdev_set_config_state(struct wireless_de
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+-wdev_prepare_prev_config(struct wireless_device *wdev)
|
||||
+-{
|
||||
+- if (wdev->prev_config)
|
||||
+- return;
|
||||
+-
|
||||
+- prepare_config(wdev, &b, false);
|
||||
+- wdev->prev_config = blob_memdup(b.head);
|
||||
+-}
|
||||
+-
|
||||
+-static void
|
||||
+ wdev_change_config(struct wireless_device *wdev, struct wireless_device *wd_new)
|
||||
+ {
|
||||
+ struct blob_attr *new_config = wd_new->config;
|
||||
+@@ -709,7 +702,6 @@ wdev_change_config(struct wireless_devic
|
||||
+ wdev->serialize = wd_new->serialize;
|
||||
+ free(wd_new);
|
||||
+
|
||||
+- wdev_prepare_prev_config(wdev);
|
||||
+ if (blob_attr_equal(wdev->config, new_config) && wdev->disabled == disabled)
|
||||
+ return;
|
||||
+
|
||||
+@@ -1533,19 +1525,78 @@ wireless_device_notify(struct wireless_d
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+-/* called on startup and by netifd reload() */
|
||||
+-void
|
||||
+-wireless_start_pending(void)
|
||||
++static void
|
||||
++wdev_check_network_enabled(struct wireless_device *wdev)
|
||||
++{
|
||||
++ struct wireless_interface *vif;
|
||||
++ struct interface *iface;
|
||||
++ struct blob_attr *cur;
|
||||
++ int rem;
|
||||
++
|
||||
++ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
++ int enabled = -1;
|
||||
++
|
||||
++ blobmsg_for_each_attr(cur, vif->network, rem) {
|
||||
++ iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
|
||||
++ if (!iface)
|
||||
++ continue;
|
||||
++
|
||||
++ if (iface->autostart) {
|
||||
++ enabled = 1;
|
||||
++ break;
|
||||
++ }
|
||||
++ if (enabled != 1)
|
||||
++ enabled = 0;
|
||||
++ }
|
||||
++
|
||||
++ if (vif->disabled == !enabled)
|
||||
++ continue;
|
||||
++
|
||||
++ vif->disabled = !enabled;
|
||||
++ wdev->config_update = true;
|
||||
++ }
|
||||
++}
|
||||
++
|
||||
++static void
|
||||
++__wireless_start_pending(struct uloop_timeout *t)
|
||||
+ {
|
||||
+ struct wireless_device *wdev;
|
||||
+
|
||||
+ vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
++ wdev_check_network_enabled(wdev);
|
||||
+ if (wdev->config_update)
|
||||
+ wdev_set_config_state(wdev, IFC_RELOAD);
|
||||
+ __wireless_device_set_up(wdev, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
++void wireless_start_pending(int timeout)
|
||||
++{
|
||||
++ static struct uloop_timeout timer = {
|
||||
++ .cb = __wireless_start_pending
|
||||
++ };
|
||||
++
|
||||
++ if (timeout) {
|
||||
++ uloop_timeout_set(&timer, timeout);
|
||||
++ return;
|
||||
++ }
|
||||
++
|
||||
++ uloop_timeout_cancel(&timer);
|
||||
++ timer.cb(&timer);
|
||||
++}
|
||||
++
|
||||
++void wireless_check_network_enabled(void)
|
||||
++{
|
||||
++ struct wireless_device *wdev;
|
||||
++
|
||||
++ vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
++ wdev_check_network_enabled(wdev);
|
||||
++
|
||||
++ if (wdev->config_update)
|
||||
++ wireless_start_pending(1000);
|
||||
++ }
|
||||
++}
|
||||
++
|
||||
+ void wireless_device_hotplug_event(const char *name, bool add)
|
||||
+ {
|
||||
+ struct wireless_interface *vif;
|
||||
+--- a/wireless.h
|
||||
++++ b/wireless.h
|
||||
+@@ -94,6 +94,7 @@ struct wireless_interface {
|
||||
+ int multicast_to_unicast;
|
||||
+ int vlan_idx;
|
||||
+ int sta_idx;
|
||||
++ bool disabled;
|
||||
+ };
|
||||
+
|
||||
+ struct wireless_vlan {
|
||||
+@@ -142,7 +143,8 @@ void wireless_station_create(struct wire
|
||||
+ int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
||||
+ struct ubus_request_data *req);
|
||||
+
|
||||
+-void wireless_start_pending(void);
|
||||
++void wireless_check_network_enabled(void);
|
||||
++void wireless_start_pending(int timeout);
|
||||
+ void wireless_init(void);
|
||||
+ void wireless_device_hotplug_event(const char *name, bool add);
|
||||
+
|
||||
--
|
||||
2.39.2
|
||||
|
||||
607
patches/backports/0061-netifd-vlan-fix.patch
Normal file
607
patches/backports/0061-netifd-vlan-fix.patch
Normal file
@@ -0,0 +1,607 @@
|
||||
From f7feafa6a88a70f96ac4bf556ff5b0665eb9735a Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Fri, 15 Sep 2023 15:01:44 +0200
|
||||
Subject: [PATCH] netifd: add wireless vlan/sta fix
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
.../patches/400-wireless_vlan_fix.patch | 587 ++++++++++++++++++
|
||||
1 file changed, 587 insertions(+)
|
||||
create mode 100644 package/network/config/netifd/patches/400-wireless_vlan_fix.patch
|
||||
|
||||
diff --git a/package/network/config/netifd/patches/400-wireless_vlan_fix.patch b/package/network/config/netifd/patches/400-wireless_vlan_fix.patch
|
||||
new file mode 100644
|
||||
index 000000000000..449121dd3d9e
|
||||
--- /dev/null
|
||||
+++ b/package/network/config/netifd/patches/400-wireless_vlan_fix.patch
|
||||
@@ -0,0 +1,587 @@
|
||||
+--- a/config.c
|
||||
++++ b/config.c
|
||||
+@@ -557,8 +557,8 @@ config_parse_wireless_device(struct uci_
|
||||
+ wireless_device_create(drv, s->e.name, b.head);
|
||||
+ }
|
||||
+
|
||||
+-static struct wireless_interface*
|
||||
+-config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
|
||||
++static void
|
||||
++config_parse_wireless_vlan(struct wireless_interface *vif, struct uci_section *s)
|
||||
+ {
|
||||
+ char *name;
|
||||
+
|
||||
+@@ -566,12 +566,12 @@ config_parse_wireless_interface(struct w
|
||||
+ sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
+
|
||||
+ blob_buf_init(&b, 0);
|
||||
+- uci_to_blob(&b, s, wdev->drv->interface.config);
|
||||
+- return wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
||||
++ uci_to_blob(&b, s, vif->wdev->drv->vlan.config);
|
||||
++ wireless_vlan_create(vif, b.head, s->anonymous ? name : s->e.name);
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+-config_parse_wireless_vlan(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
||||
++config_parse_wireless_station(struct wireless_interface *vif, struct uci_section *s)
|
||||
+ {
|
||||
+ char *name;
|
||||
+
|
||||
+@@ -579,21 +579,62 @@ config_parse_wireless_vlan(struct wirele
|
||||
+ sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
+
|
||||
+ blob_buf_init(&b, 0);
|
||||
+- uci_to_blob(&b, s, wdev->drv->vlan.config);
|
||||
+- wireless_vlan_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
||||
++ uci_to_blob(&b, s, vif->wdev->drv->station.config);
|
||||
++ wireless_station_create(vif, b.head, s->anonymous ? name : s->e.name);
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+-config_parse_wireless_station(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
||||
++config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
|
||||
+ {
|
||||
++ struct wireless_interface *vif;
|
||||
++ struct uci_element *f;
|
||||
+ char *name;
|
||||
+
|
||||
+ name = alloca(strlen(s->type) + 16);
|
||||
+ sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
||||
+
|
||||
+ blob_buf_init(&b, 0);
|
||||
+- uci_to_blob(&b, s, wdev->drv->station.config);
|
||||
+- wireless_station_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
||||
++ uci_to_blob(&b, s, wdev->drv->interface.config);
|
||||
++ vif = wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
||||
++ if (!vif)
|
||||
++ return;
|
||||
++
|
||||
++ vif->vlan_idx = vif->sta_idx = 0;
|
||||
++ vlist_update(&vif->vlans);
|
||||
++ vlist_update(&vif->stations);
|
||||
++
|
||||
++ if (s->anonymous)
|
||||
++ goto out;
|
||||
++
|
||||
++ uci_foreach_element(&uci_wireless->sections, f) {
|
||||
++ struct uci_section *cur = uci_to_section(f);
|
||||
++ const char *vif_name;
|
||||
++
|
||||
++ if (strcmp(cur->type, "wifi-vlan") != 0)
|
||||
++ continue;
|
||||
++
|
||||
++ vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
|
||||
++ if (vif_name && strcmp(s->e.name, vif_name))
|
||||
++ continue;
|
||||
++ config_parse_wireless_vlan(vif, cur);
|
||||
++ }
|
||||
++
|
||||
++ uci_foreach_element(&uci_wireless->sections, f) {
|
||||
++ struct uci_section *cur = uci_to_section(f);
|
||||
++ const char *vif_name;
|
||||
++
|
||||
++ if (strcmp(cur->type, "wifi-station") != 0)
|
||||
++ continue;
|
||||
++
|
||||
++ vif_name = uci_lookup_option_string(uci_ctx, cur, "iface");
|
||||
++ if (vif_name && strcmp(s->e.name, vif_name))
|
||||
++ continue;
|
||||
++ config_parse_wireless_station(vif, cur);
|
||||
++ }
|
||||
++
|
||||
++out:
|
||||
++ vlist_flush(&vif->vlans);
|
||||
++ vlist_flush(&vif->stations);
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+@@ -623,16 +664,10 @@ config_init_wireless(void)
|
||||
+ vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
+ wdev->vif_idx = 0;
|
||||
+ vlist_update(&wdev->interfaces);
|
||||
+- wdev->vlan_idx = 0;
|
||||
+- vlist_update(&wdev->vlans);
|
||||
+- wdev->sta_idx = 0;
|
||||
+- vlist_update(&wdev->stations);
|
||||
+ }
|
||||
+
|
||||
+ uci_foreach_element(&uci_wireless->sections, e) {
|
||||
+ struct uci_section *s = uci_to_section(e);
|
||||
+- struct wireless_interface *vif;
|
||||
+- struct uci_element *f;
|
||||
+
|
||||
+ if (strcmp(s->type, "wifi-iface") != 0)
|
||||
+ continue;
|
||||
+@@ -647,42 +682,11 @@ config_init_wireless(void)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+- vif = config_parse_wireless_interface(wdev, s);
|
||||
+-
|
||||
+- if (!vif || s->anonymous)
|
||||
+- continue;
|
||||
+- uci_foreach_element(&uci_wireless->sections, f) {
|
||||
+- struct uci_section *s = uci_to_section(f);
|
||||
+- const char *vif_name;
|
||||
+-
|
||||
+- if (strcmp(s->type, "wifi-vlan") != 0)
|
||||
+- continue;
|
||||
+-
|
||||
+- vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
||||
+- if (vif_name && strcmp(e->name, vif_name))
|
||||
+- continue;
|
||||
+- config_parse_wireless_vlan(wdev, vif->name, s);
|
||||
+- }
|
||||
+-
|
||||
+- uci_foreach_element(&uci_wireless->sections, f) {
|
||||
+- struct uci_section *s = uci_to_section(f);
|
||||
+- const char *vif_name;
|
||||
+-
|
||||
+- if (strcmp(s->type, "wifi-station") != 0)
|
||||
+- continue;
|
||||
+-
|
||||
+- vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
||||
+- if (vif_name && strcmp(e->name, vif_name))
|
||||
+- continue;
|
||||
+- config_parse_wireless_station(wdev, vif->name, s);
|
||||
+- }
|
||||
++ config_parse_wireless_interface(wdev, s);
|
||||
+ }
|
||||
+
|
||||
+- vlist_for_each_element(&wireless_devices, wdev, node) {
|
||||
++ vlist_for_each_element(&wireless_devices, wdev, node)
|
||||
+ vlist_flush(&wdev->interfaces);
|
||||
+- vlist_flush(&wdev->vlans);
|
||||
+- vlist_flush(&wdev->stations);
|
||||
+- }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+--- a/scripts/netifd-wireless.sh
|
||||
++++ b/scripts/netifd-wireless.sh
|
||||
+@@ -108,14 +108,16 @@ _wdev_wrapper() {
|
||||
+ }
|
||||
+
|
||||
+ _wdev_notify_init() {
|
||||
+- local command="$1"
|
||||
+- local name="$2"
|
||||
+- local value="$3"
|
||||
++ local command="$1"; shift;
|
||||
+
|
||||
+ json_init
|
||||
+ json_add_int "command" "$command"
|
||||
+ json_add_string "device" "$__netifd_device"
|
||||
+- [ -n "$name" -a -n "$value" ] && json_add_string "$name" "$value"
|
||||
++ while [ -n "$1" ]; do
|
||||
++ local name="$1"; shift
|
||||
++ local value="$1"; shift
|
||||
++ json_add_string "$name" "$value"
|
||||
++ done
|
||||
+ json_add_object "data"
|
||||
+ }
|
||||
+
|
||||
+@@ -151,7 +153,7 @@ _wireless_add_vlan() {
|
||||
+ local name="$1"; shift
|
||||
+ local ifname="$1"; shift
|
||||
+
|
||||
+- _wdev_notify_init $CMD_SET_DATA "vlan" "$name"
|
||||
++ _wdev_notify_init $CMD_SET_DATA interface "$__cur_interface" "vlan" "$name"
|
||||
+ json_add_string "ifname" "$ifname"
|
||||
+ _wdev_add_variables "$@"
|
||||
+ _wdev_notify
|
||||
+@@ -333,6 +335,7 @@ for_each_interface() {
|
||||
+ continue
|
||||
+ }
|
||||
+ fi
|
||||
++ __cur_interface="$_w_iface"
|
||||
+ "$@" "$_w_iface"
|
||||
+ json_select ..
|
||||
+ done
|
||||
+--- a/wireless.c
|
||||
++++ b/wireless.c
|
||||
+@@ -205,9 +205,7 @@ prepare_config(struct wireless_device *w
|
||||
+ blobmsg_add_blob(&b, vif->data);
|
||||
+
|
||||
+ j = blobmsg_open_table(&b, "vlans");
|
||||
+- vlist_for_each_element(&wdev->vlans, vlan, node) {
|
||||
+- if (strcmp(vlan->vif, vif->name))
|
||||
+- continue;
|
||||
++ vlist_for_each_element(&vif->vlans, vlan, node) {
|
||||
+ k = blobmsg_open_table(&b, vlan->name);
|
||||
+ vif_config_add_bridge(&b, vlan->network, up);
|
||||
+ put_container(&b, vlan->config, "config");
|
||||
+@@ -218,9 +216,7 @@ prepare_config(struct wireless_device *w
|
||||
+ blobmsg_close_table(&b, j);
|
||||
+
|
||||
+ j = blobmsg_open_table(&b, "stas");
|
||||
+- vlist_for_each_element(&wdev->stations, sta, node) {
|
||||
+- if (strcmp(sta->vif, vif->name))
|
||||
+- continue;
|
||||
++ vlist_for_each_element(&vif->stations, sta, node) {
|
||||
+ k = blobmsg_open_table(&b, sta->name);
|
||||
+ put_container(&b, sta->config, "config");
|
||||
+ if (sta->data)
|
||||
+@@ -311,15 +307,15 @@ wireless_device_free_state(struct wirele
|
||||
+ free(vif->data);
|
||||
+ vif->data = NULL;
|
||||
+ vif->ifname = NULL;
|
||||
+- }
|
||||
+- vlist_for_each_element(&wdev->vlans, vlan, node) {
|
||||
+- free(vlan->data);
|
||||
+- vlan->data = NULL;
|
||||
+- vlan->ifname = NULL;
|
||||
+- }
|
||||
+- vlist_for_each_element(&wdev->stations, sta, node) {
|
||||
+- free(sta->data);
|
||||
+- sta->data = NULL;
|
||||
++ vlist_for_each_element(&vif->vlans, vlan, node) {
|
||||
++ free(vlan->data);
|
||||
++ vlan->data = NULL;
|
||||
++ vlan->ifname = NULL;
|
||||
++ }
|
||||
++ vlist_for_each_element(&vif->stations, sta, node) {
|
||||
++ free(sta->data);
|
||||
++ sta->data = NULL;
|
||||
++ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+@@ -510,8 +506,6 @@ wireless_device_free(struct wireless_dev
|
||||
+ {
|
||||
+ wireless_handler_stop(wdev);
|
||||
+ vlist_flush_all(&wdev->interfaces);
|
||||
+- vlist_flush_all(&wdev->vlans);
|
||||
+- vlist_flush_all(&wdev->stations);
|
||||
+ avl_delete(&wireless_devices.avl, &wdev->node.avl);
|
||||
+ free(wdev->config);
|
||||
+ free(wdev->prev_config);
|
||||
+@@ -547,11 +541,12 @@ wireless_device_mark_down(struct wireles
|
||||
+
|
||||
+ netifd_log_message(L_NOTICE, "Wireless device '%s' is now down\n", wdev->name);
|
||||
+
|
||||
+- vlist_for_each_element(&wdev->vlans, vlan, node)
|
||||
+- wireless_vlan_handle_link(vlan, false);
|
||||
+
|
||||
+- vlist_for_each_element(&wdev->interfaces, vif, node)
|
||||
++ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
+ wireless_interface_handle_link(vif, NULL, false);
|
||||
++ vlist_for_each_element(&vif->vlans, vlan, node)
|
||||
++ wireless_vlan_handle_link(vlan, false);
|
||||
++ }
|
||||
+
|
||||
+ wireless_process_kill_all(wdev, SIGTERM, true);
|
||||
+
|
||||
+@@ -623,10 +618,11 @@ wireless_device_mark_up(struct wireless_
|
||||
+ netifd_log_message(L_NOTICE, "Wireless device '%s' is now up\n", wdev->name);
|
||||
+ wdev->retry = WIRELESS_SETUP_RETRY;
|
||||
+ wdev->state = IFS_UP;
|
||||
+- vlist_for_each_element(&wdev->interfaces, vif, node)
|
||||
++ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
||||
+ wireless_interface_handle_link(vif, NULL, true);
|
||||
+- vlist_for_each_element(&wdev->vlans, vlan, node)
|
||||
+- wireless_vlan_handle_link(vlan, true);
|
||||
++ vlist_for_each_element(&vif->vlans, vlan, node)
|
||||
++ wireless_vlan_handle_link(vlan, true);
|
||||
++ }
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+@@ -848,6 +844,16 @@ wireless_interface_init_config(struct wi
|
||||
+ vif->multicast_to_unicast = cur ? blobmsg_get_bool(cur) : -1;
|
||||
+ }
|
||||
+
|
||||
++static void
|
||||
++vif_free(struct wireless_interface *vif)
|
||||
++{
|
||||
++ vlist_flush_all(&vif->vlans);
|
||||
++ vlist_flush_all(&vif->stations);
|
||||
++ free((void *) vif->section);
|
||||
++ free(vif->config);
|
||||
++ free(vif);
|
||||
++}
|
||||
++
|
||||
+ /* vlist update call for wireless interface list */
|
||||
+ static void
|
||||
+ vif_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
+@@ -884,9 +890,7 @@ vif_update(struct vlist_tree *tree, stru
|
||||
+ } else if (vif_old) {
|
||||
+ D(WIRELESS, "Delete wireless interface %s on device %s\n", vif_old->name, wdev->name);
|
||||
+ wireless_interface_handle_link(vif_old, NULL, false);
|
||||
+- free((void *) vif_old->section);
|
||||
+- free(vif_old->config);
|
||||
+- free(vif_old);
|
||||
++ vif_free(vif_old);
|
||||
+ }
|
||||
+
|
||||
+ wdev->config_update = true;
|
||||
+@@ -921,14 +925,10 @@ static void
|
||||
+ vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
+ struct vlist_node *node_old)
|
||||
+ {
|
||||
+- struct wireless_vlan *vlan_old = container_of(node_old, struct wireless_vlan, node);
|
||||
+- struct wireless_vlan *vlan_new = container_of(node_new, struct wireless_vlan, node);
|
||||
+- struct wireless_device *wdev;
|
||||
+-
|
||||
+- if (vlan_old)
|
||||
+- wdev = vlan_old->wdev;
|
||||
+- else
|
||||
+- wdev = vlan_new->wdev;
|
||||
++ struct wireless_vlan *vlan_old = container_of_safe(node_old, struct wireless_vlan, node);
|
||||
++ struct wireless_vlan *vlan_new = container_of_safe(node_new, struct wireless_vlan, node);
|
||||
++ struct wireless_interface *vif = container_of(tree, struct wireless_interface, vlans);
|
||||
++ struct wireless_device *wdev = vif->wdev;
|
||||
+
|
||||
+ if (vlan_old && vlan_new) {
|
||||
+ free((void *) vlan_old->section);
|
||||
+@@ -951,7 +951,7 @@ vlan_update(struct vlist_tree *tree, str
|
||||
+ vlan_new->config = blob_memdup(vlan_new->config);
|
||||
+ wireless_vlan_init_config(vlan_new);
|
||||
+ } else if (vlan_old) {
|
||||
+- D(WIRELESS, "Delete wireless interface %s on device %s\n", vlan_old->name, wdev->name);
|
||||
++ D(WIRELESS, "Delete wireless vlan %s on device %s\n", vlan_old->name, wdev->name);
|
||||
+ wireless_vlan_handle_link(vlan_old, false);
|
||||
+ free((void *) vlan_old->section);
|
||||
+ free(vlan_old->config);
|
||||
+@@ -966,14 +966,10 @@ static void
|
||||
+ station_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
||||
+ struct vlist_node *node_old)
|
||||
+ {
|
||||
+- struct wireless_station *sta_old = container_of(node_old, struct wireless_station, node);
|
||||
+- struct wireless_station *sta_new = container_of(node_new, struct wireless_station, node);
|
||||
+- struct wireless_device *wdev;
|
||||
+-
|
||||
+- if (sta_old)
|
||||
+- wdev = sta_old->wdev;
|
||||
+- else
|
||||
+- wdev = sta_new->wdev;
|
||||
++ struct wireless_station *sta_old = container_of_safe(node_old, struct wireless_station, node);
|
||||
++ struct wireless_station *sta_new = container_of_safe(node_new, struct wireless_station, node);
|
||||
++ struct wireless_interface *vif = container_of(tree, struct wireless_interface, stations);
|
||||
++ struct wireless_device *wdev = vif->wdev;
|
||||
+
|
||||
+ if (sta_old && sta_new) {
|
||||
+ free((void *) sta_old->section);
|
||||
+@@ -1088,10 +1084,6 @@ wireless_device_create(struct wireless_d
|
||||
+ INIT_LIST_HEAD(&wdev->script_proc);
|
||||
+ vlist_init(&wdev->interfaces, avl_strcmp, vif_update);
|
||||
+ wdev->interfaces.keep_old = true;
|
||||
+- vlist_init(&wdev->vlans, avl_strcmp, vlan_update);
|
||||
+- wdev->vlans.keep_old = true;
|
||||
+- vlist_init(&wdev->stations, avl_strcmp, station_update);
|
||||
+- wdev->stations.keep_old = true;
|
||||
+
|
||||
+ wdev->timeout.cb = wireless_device_setup_timeout;
|
||||
+ wdev->script_task.cb = wireless_device_script_task_cb;
|
||||
+@@ -1108,12 +1100,12 @@ wireless_device_create(struct wireless_d
|
||||
+
|
||||
+ /* creates a wireless station object. Called by config */
|
||||
+ void
|
||||
+-wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
||||
++wireless_station_create(struct wireless_interface *vif, struct blob_attr *data, const char *section)
|
||||
+ {
|
||||
+ struct wireless_station *sta;
|
||||
+ struct blob_attr *tb[__STA_ATTR_MAX];
|
||||
+ struct blob_attr *cur;
|
||||
+- char *name_buf, *vif_buf;
|
||||
++ char *name_buf;
|
||||
+ char name[8];
|
||||
+
|
||||
+ blobmsg_parse(sta_policy, __STA_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
||||
+@@ -1122,18 +1114,15 @@ wireless_station_create(struct wireless_
|
||||
+ if (cur && blobmsg_get_bool(cur))
|
||||
+ return;
|
||||
+
|
||||
+- sprintf(name, "%d", wdev->sta_idx++);
|
||||
++ sprintf(name, "%d", vif->sta_idx++);
|
||||
+
|
||||
+ sta = calloc_a(sizeof(*sta),
|
||||
+- &name_buf, strlen(name) + 1,
|
||||
+- &vif_buf, strlen(vif) + 1);
|
||||
++ &name_buf, strlen(name) + 1);
|
||||
+ sta->name = strcpy(name_buf, name);
|
||||
+- sta->vif = strcpy(vif_buf, vif);
|
||||
+- sta->wdev = wdev;
|
||||
+ sta->config = data;
|
||||
+ sta->section = section;
|
||||
+
|
||||
+- vlist_add(&wdev->stations, &sta->node, sta->name);
|
||||
++ vlist_add(&vif->stations, &sta->node, sta->name);
|
||||
+ }
|
||||
+
|
||||
+ /* ubus callback network.wireless.status, runs for every interface, encode the station */
|
||||
+@@ -1151,12 +1140,12 @@ wireless_station_status(struct wireless_
|
||||
+
|
||||
+ /* create a vlan object. Called by config */
|
||||
+ void
|
||||
+-wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
||||
++wireless_vlan_create(struct wireless_interface *vif, struct blob_attr *data, const char *section)
|
||||
+ {
|
||||
+ struct wireless_vlan *vlan;
|
||||
+ struct blob_attr *tb[__VLAN_ATTR_MAX];
|
||||
+ struct blob_attr *cur;
|
||||
+- char *name_buf, *vif_buf;
|
||||
++ char *name_buf;
|
||||
+ char name[8];
|
||||
+
|
||||
+ blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
||||
+@@ -1165,19 +1154,14 @@ wireless_vlan_create(struct wireless_dev
|
||||
+ if (cur && blobmsg_get_bool(cur))
|
||||
+ return;
|
||||
+
|
||||
+- sprintf(name, "%d", wdev->vlan_idx++);
|
||||
++ sprintf(name, "%d", vif->vlan_idx++);
|
||||
+
|
||||
+- vlan = calloc_a(sizeof(*vlan),
|
||||
+- &name_buf, strlen(name) + 1,
|
||||
+- &vif_buf, strlen(vif) + 1);
|
||||
++ vlan = calloc_a(sizeof(*vlan), &name_buf, strlen(name) + 1);
|
||||
+ vlan->name = strcpy(name_buf, name);
|
||||
+- vlan->vif = strcpy(vif_buf, vif);
|
||||
+- vlan->wdev = wdev;
|
||||
+ vlan->config = data;
|
||||
+ vlan->section = section;
|
||||
+- vlan->isolate = false;
|
||||
+
|
||||
+- vlist_add(&wdev->vlans, &vlan->node, vlan->name);
|
||||
++ vlist_add(&vif->vlans, &vlan->node, vlan->name);
|
||||
+ }
|
||||
+
|
||||
+ /* ubus callback network.wireless.status, runs for every interface, encode the vlan informations */
|
||||
+@@ -1220,6 +1204,12 @@ struct wireless_interface* wireless_inte
|
||||
+ vif->section = section;
|
||||
+ vif->isolate = false;
|
||||
+
|
||||
++ vlist_init(&vif->vlans, avl_strcmp, vlan_update);
|
||||
++ vif->vlans.keep_old = true;
|
||||
++
|
||||
++ vlist_init(&vif->stations, avl_strcmp, station_update);
|
||||
++ vif->stations.keep_old = true;
|
||||
++
|
||||
+ vlist_add(&wdev->interfaces, &vif->node, vif->name);
|
||||
+
|
||||
+ return vlist_find(&wdev->interfaces, name, vif, node);
|
||||
+@@ -1240,14 +1230,12 @@ wireless_interface_status(struct wireles
|
||||
+ blobmsg_add_string(b, "ifname", iface->ifname);
|
||||
+ put_container(b, iface->config, "config");
|
||||
+ j = blobmsg_open_array(b, "vlans");
|
||||
+- vlist_for_each_element(&iface->wdev->vlans, vlan, node)
|
||||
+- if (!strcmp(iface->name, vlan->vif))
|
||||
+- wireless_vlan_status(vlan, b);
|
||||
++ vlist_for_each_element(&iface->vlans, vlan, node)
|
||||
++ wireless_vlan_status(vlan, b);
|
||||
+ blobmsg_close_array(b, j);
|
||||
+ j = blobmsg_open_array(b, "stations");
|
||||
+- vlist_for_each_element(&iface->wdev->stations, sta, node)
|
||||
+- if (!strcmp(iface->name, sta->vif))
|
||||
+- wireless_station_status(sta, b);
|
||||
++ vlist_for_each_element(&iface->stations, sta, node)
|
||||
++ wireless_station_status(sta, b);
|
||||
+ blobmsg_close_array(b, j);
|
||||
+ blobmsg_close_table(b, i);
|
||||
+ }
|
||||
+@@ -1496,7 +1484,9 @@ wireless_device_notify(struct wireless_d
|
||||
+ }
|
||||
+
|
||||
+ if ((cur = tb[NOTIFY_ATTR_VLAN]) != NULL) {
|
||||
+- vlan = vlist_find(&wdev->vlans, blobmsg_data(cur), vlan, node);
|
||||
++ if (!vif)
|
||||
++ return UBUS_STATUS_NOT_FOUND;
|
||||
++ vlan = vlist_find(&vif->vlans, blobmsg_data(cur), vlan, node);
|
||||
+ if (!vlan)
|
||||
+ return UBUS_STATUS_NOT_FOUND;
|
||||
+ }
|
||||
+@@ -1516,19 +1506,19 @@ wireless_device_notify(struct wireless_d
|
||||
+ wireless_device_mark_up(wdev);
|
||||
+ break;
|
||||
+ case NOTIFY_CMD_SET_DATA:
|
||||
+- if (vif)
|
||||
+- pdata = &vif->data;
|
||||
+- else if (vlan)
|
||||
++ if (vlan)
|
||||
+ pdata = &vlan->data;
|
||||
++ else if (vif)
|
||||
++ pdata = &vif->data;
|
||||
+ else
|
||||
+ pdata = &wdev->data;
|
||||
+
|
||||
+ free(*pdata);
|
||||
+ *pdata = blob_memdup(cur);
|
||||
+- if (vif)
|
||||
+- wireless_interface_set_data(vif);
|
||||
+- else if (vlan)
|
||||
++ if (vlan)
|
||||
+ wireless_vlan_set_data(vlan);
|
||||
++ else if (vif)
|
||||
++ wireless_interface_set_data(vif);
|
||||
+ break;
|
||||
+ case NOTIFY_CMD_PROCESS_ADD:
|
||||
+ return wireless_device_add_process(wdev, cur);
|
||||
+--- a/wireless.h
|
||||
++++ b/wireless.h
|
||||
+@@ -44,8 +44,6 @@ struct wireless_device {
|
||||
+
|
||||
+ struct wireless_driver *drv;
|
||||
+ struct vlist_tree interfaces;
|
||||
+- struct vlist_tree vlans;
|
||||
+- struct vlist_tree stations;
|
||||
+ char *name;
|
||||
+
|
||||
+ struct netifd_process script_task;
|
||||
+@@ -73,8 +71,6 @@ struct wireless_device {
|
||||
+ int retry;
|
||||
+
|
||||
+ int vif_idx;
|
||||
+- int vlan_idx;
|
||||
+- int sta_idx;
|
||||
+ };
|
||||
+
|
||||
+ struct wireless_interface {
|
||||
+@@ -82,6 +78,8 @@ struct wireless_interface {
|
||||
+ const char *section;
|
||||
+ char *name;
|
||||
+
|
||||
++ struct vlist_tree vlans;
|
||||
++ struct vlist_tree stations;
|
||||
+ struct wireless_device *wdev;
|
||||
+
|
||||
+ struct blob_attr *config;
|
||||
+@@ -94,6 +92,8 @@ struct wireless_interface {
|
||||
+ bool isolate;
|
||||
+ bool ap_mode;
|
||||
+ int multicast_to_unicast;
|
||||
++ int vlan_idx;
|
||||
++ int sta_idx;
|
||||
+ };
|
||||
+
|
||||
+ struct wireless_vlan {
|
||||
+@@ -101,9 +101,6 @@ struct wireless_vlan {
|
||||
+ const char *section;
|
||||
+ char *name;
|
||||
+
|
||||
+- struct wireless_device *wdev;
|
||||
+- char *vif;
|
||||
+-
|
||||
+ struct blob_attr *config;
|
||||
+ struct blob_attr *data;
|
||||
+
|
||||
+@@ -119,9 +116,6 @@ struct wireless_station {
|
||||
+ const char *section;
|
||||
+ char *name;
|
||||
+
|
||||
+- struct wireless_device *wdev;
|
||||
+- char *vif;
|
||||
+-
|
||||
+ struct blob_attr *config;
|
||||
+ struct blob_attr *data;
|
||||
+ };
|
||||
+@@ -143,8 +137,8 @@ void wireless_device_reconf(struct wirel
|
||||
+ void wireless_device_status(struct wireless_device *wdev, struct blob_buf *b);
|
||||
+ void wireless_device_get_validate(struct wireless_device *wdev, struct blob_buf *b);
|
||||
+ struct wireless_interface* wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
||||
+-void wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
||||
+-void wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
||||
++void wireless_vlan_create(struct wireless_interface *vif, struct blob_attr *data, const char *section);
|
||||
++void wireless_station_create(struct wireless_interface *vif, struct blob_attr *data, const char *section);
|
||||
+ int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
||||
+ struct ubus_request_data *req);
|
||||
+
|
||||
--
|
||||
2.39.2
|
||||
|
||||
@@ -381,9 +381,9 @@ index 65ae662c4d..90d9210410 100644
|
||||
# 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
|
||||
+ vlan_possible=1
|
||||
+ [ "$macfilter" = radius ] && {
|
||||
+ append_radius_server
|
||||
+ vlan_possible=1
|
||||
+ }
|
||||
;;
|
||||
psk|sae|psk-sae)
|
||||
|
||||
26
profiles/cig_wf186h.yml
Normal file
26
profiles/cig_wf186h.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
profile: cig_wf186h
|
||||
target: ipq807x
|
||||
subtarget: ipq50xx
|
||||
description: Build image for the Cigtech Wall Plate WF186h
|
||||
image: bin/targets/ipq807x/ipq50xx/openwrt-ipq807x-cig_wf186h-squashfs-sysupgrade.tar
|
||||
feeds:
|
||||
- name: ipq807x
|
||||
path: ../../feeds/ipq807x
|
||||
include:
|
||||
- wifi-ax
|
||||
- ucentral-ap
|
||||
packages:
|
||||
- ipq807x
|
||||
- ath11k-fwtest
|
||||
- ftm
|
||||
|
||||
diffconfig: |
|
||||
CONFIG_PACKAGE_i2c-tools=y
|
||||
CONFIG_PACKAGE_libi2c=y
|
||||
CONFIG_PACKAGE_coreutils=y
|
||||
CONFIG_PACKAGE_coreutils-stty=y
|
||||
CONFIG_PACKAGE_kmod-switch-rtl8366-smi=y
|
||||
CONFIG_PACKAGE_kmod-switch-rtl8367c=y
|
||||
|
||||
|
||||
Reference in New Issue
Block a user