Page MenuHomeVyOS Platform

No OneTemporary

Size
78 KB
Referenced Files
None
Subscribers
None
diff --git a/data/config-mode-dependencies/vyos-1x.json b/data/config-mode-dependencies/vyos-1x.json
index ca4ceb58f..a38635cbe 100644
--- a/data/config-mode-dependencies/vyos-1x.json
+++ b/data/config-mode-dependencies/vyos-1x.json
@@ -1,67 +1,70 @@
{
"system_conntrack": {
"conntrack_sync": ["service_conntrack-sync"],
"vrf": ["vrf"]
},
"firewall": {
"conntrack": ["system_conntrack"],
"group_resync": ["system_conntrack", "nat", "policy_route"]
},
"interfaces_bonding": {
"ethernet": ["interfaces_ethernet"]
},
"interfaces_bridge": {
"vxlan": ["interfaces_vxlan"],
"wlan": ["interfaces_wireless"]
},
"load_balancing_wan": {
"conntrack": ["system_conntrack"]
},
"nat": {
"conntrack": ["system_conntrack"]
},
"nat66": {
"conntrack": ["system_conntrack"]
},
"pki": {
"ethernet": ["interfaces_ethernet"],
"openvpn": ["interfaces_openvpn"],
"https": ["service_https"],
"ipsec": ["vpn_ipsec"],
"openconnect": ["vpn_openconnect"],
"reverse_proxy": ["load-balancing_reverse-proxy"],
"rpki": ["protocols_rpki"],
"sstp": ["vpn_sstp"],
"sstpc": ["interfaces_sstpc"]
},
"vpn_ipsec": {
"nhrp": ["protocols_nhrp"]
},
"vpn_l2tp": {
"ipsec": ["vpn_ipsec"]
},
"qos": {
"bonding": ["interfaces_bonding"],
"bridge": ["interfaces_bridge"],
"dummy": ["interfaces_dummy"],
"ethernet": ["interfaces_ethernet"],
"geneve": ["interfaces_geneve"],
"input": ["interfaces_input"],
"l2tpv3": ["interfaces_l2tpv3"],
"loopback": ["interfaces_loopback"],
"macsec": ["interfaces_macsec"],
"openvpn": ["interfaces_openvpn"],
"pppoe": ["interfaces_pppoe"],
"pseudo-ethernet": ["interfaces_pseudo-ethernet"],
"tunnel": ["interfaces_tunnel"],
"vti": ["interfaces_vti"],
"vxlan": ["interfaces_vxlan"],
"wireguard": ["interfaces_wireguard"],
"wireless": ["interfaces_wireless"],
"wwan": ["interfaces_wwan"]
},
"system_option": {
"ip": ["system_ip"],
"ipv6": ["system_ipv6"]
+ },
+ "system_wireless": {
+ "wireless": ["interfaces_wireless"]
}
}
diff --git a/data/configd-include.json b/data/configd-include.json
index 420960fe7..b92d58c72 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -1,113 +1,114 @@
[
"container.py",
"firewall.py",
"high-availability.py",
"interfaces_bonding.py",
"interfaces_bridge.py",
"interfaces_dummy.py",
"interfaces_ethernet.py",
"interfaces_geneve.py",
"interfaces_input.py",
"interfaces_l2tpv3.py",
"interfaces_loopback.py",
"interfaces_macsec.py",
"interfaces_openvpn.py",
"interfaces_pppoe.py",
"interfaces_pseudo-ethernet.py",
"interfaces_sstpc.py",
"interfaces_tunnel.py",
"interfaces_virtual-ethernet.py",
"interfaces_vti.py",
"interfaces_vxlan.py",
"interfaces_wireguard.py",
"interfaces_wireless.py",
"interfaces_wwan.py",
"load-balancing_reverse-proxy.py",
"load-balancing_wan.py",
"nat.py",
"nat64.py",
"nat66.py",
"netns.py",
"pki.py",
"policy.py",
"policy_route.py",
"policy_local-route.py",
"protocols_babel.py",
"protocols_bfd.py",
"protocols_bgp.py",
"protocols_eigrp.py",
"protocols_failover.py",
"protocols_igmp-proxy.py",
"protocols_isis.py",
"protocols_mpls.py",
"protocols_nhrp.py",
"protocols_ospf.py",
"protocols_ospfv3.py",
"protocols_pim.py",
"protocols_pim6.py",
"protocols_rip.py",
"protocols_ripng.py",
"protocols_rpki.py",
"protocols_segment-routing.py",
"protocols_static.py",
"protocols_static_arp.py",
"protocols_static_multicast.py",
"protocols_static_neighbor-proxy.py",
"qos.py",
"service_aws_glb.py",
"service_broadcast-relay.py",
"service_config-sync.py",
"service_conntrack-sync.py",
"service_console-server.py",
"service_dhcp-relay.py",
"service_dhcp-server.py",
"service_dhcpv6-relay.py",
"service_dhcpv6-server.py",
"service_dns_dynamic.py",
"service_dns_forwarding.py",
"service_event-handler.py",
"service_https.py",
"service_ids_ddos-protection.py",
"service_ipoe-server.py",
"service_lldp.py",
"service_mdns_repeater.py",
"service_monitoring_telegraf.py",
"service_monitoring_zabbix-agent.py",
"service_ndp-proxy.py",
"service_ntp.py",
"service_pppoe-server.py",
"service_router-advert.py",
"service_salt-minion.py",
"service_sla.py",
"service_snmp.py",
"service_ssh.py",
"service_tftp-server.py",
"service_webproxy.py",
"system_acceleration.py",
"system_config-management.py",
"system_conntrack.py",
"system_console.py",
"system_flow-accounting.py",
"system_frr.py",
"system_host-name.py",
"system_ip.py",
"system_ipv6.py",
"system_lcd.py",
"system_login.py",
"system_login_banner.py",
"system_logs.py",
"system_option.py",
"system_proxy.py",
"system_sflow.py",
"system_sysctl.py",
"system_syslog.py",
"system_task-scheduler.py",
"system_timezone.py",
"system_update-check.py",
+"system_wireless.py",
"vpn_ipsec.py",
"vpn_l2tp.py",
"vpn_openconnect.py",
"vpn_pptp.py",
"vpn_sstp.py",
"vrf.py"
]
diff --git a/interface-definitions/include/version/interfaces-version.xml.i b/interface-definitions/include/version/interfaces-version.xml.i
index 854e60f4e..2915b318e 100644
--- a/interface-definitions/include/version/interfaces-version.xml.i
+++ b/interface-definitions/include/version/interfaces-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/interfaces-version.xml.i -->
-<syntaxVersion component='interfaces' version='32'></syntaxVersion>
+<syntaxVersion component='interfaces' version='33'></syntaxVersion>
<!-- include end -->
diff --git a/interface-definitions/interfaces_wireless.xml.in b/interface-definitions/interfaces_wireless.xml.in
index d69daa485..0a62b3255 100644
--- a/interface-definitions/interfaces_wireless.xml.in
+++ b/interface-definitions/interfaces_wireless.xml.in
@@ -1,996 +1,976 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="interfaces">
<children>
<tagNode name="wireless" owner="${vyos_conf_scripts_dir}/interfaces_wireless.py">
<properties>
<help>Wireless (WiFi/WLAN) Network Interface</help>
<priority>318</priority>
<completionHelp>
<script>cd /sys/class/net; if compgen -G "wlan*" > /dev/null; then ls -d wlan*; fi</script>
</completionHelp>
<constraint>
<regex>wlan[0-9]+</regex>
</constraint>
<constraintErrorMessage>Wireless interface must be named wlanN</constraintErrorMessage>
<valueHelp>
<format>wlanN</format>
<description>Wireless (WiFi/WLAN) interface name</description>
</valueHelp>
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
<node name="capabilities">
<properties>
<help>HT and VHT capabilities for your card</help>
</properties>
<children>
<node name="ht">
<properties>
<help>High Throughput (HT) settings</help>
</properties>
<children>
<leafNode name="40mhz-incapable">
<properties>
<help>40MHz intolerance, use 20MHz only!</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="auto-powersave">
<properties>
<help>Enable WMM-PS unscheduled automatic power save delivery [U-APSD]</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="channel-set-width">
<properties>
<help>Supported channel set width</help>
<completionHelp>
<list>ht20 ht40+ ht40-</list>
</completionHelp>
<valueHelp>
<format>ht20</format>
<description>Supported channel set width both 20 MHz only</description>
</valueHelp>
<valueHelp>
<format>ht40+</format>
<description>Supported channel set width both 20 MHz and 40 MHz with secondary channel above primary channel</description>
</valueHelp>
<valueHelp>
<format>ht40-</format>
<description>Supported channel set width both 20 MHz and 40 MHz with secondary channel below primary channel</description>
</valueHelp>
<constraint>
<regex>(ht20|ht40\+|ht40-)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="delayed-block-ack">
<properties>
<help>Enable HT-delayed block ack</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="dsss-cck-40">
<properties>
<help>Enable DSSS_CCK-40</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="greenfield">
<properties>
<help>Enable HT-greenfield</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="ldpc">
<properties>
<help>Enable LDPC coding capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="lsig-protection">
<properties>
<help>Enable L-SIG TXOP protection capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="max-amsdu">
<properties>
<help>Set maximum A-MSDU length</help>
<completionHelp>
<list>3839 7935</list>
</completionHelp>
<valueHelp>
<format>3839</format>
<description>Set maximum A-MSDU length to 3839 octets</description>
</valueHelp>
<valueHelp>
<format>7935</format>
<description>Set maximum A-MSDU length to 7935 octets</description>
</valueHelp>
<constraint>
<regex>(3839|7935)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="short-gi">
<properties>
<help>Short GI capabilities</help>
<completionHelp>
<list>20 40</list>
</completionHelp>
<valueHelp>
<format>20</format>
<description>Short GI for 20 MHz</description>
</valueHelp>
<valueHelp>
<format>40</format>
<description>Short GI for 40 MHz</description>
</valueHelp>
<constraint>
<regex>(20|40)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="smps">
<properties>
<help>Spatial Multiplexing Power Save (SMPS) settings</help>
<completionHelp>
<list>static dynamic</list>
</completionHelp>
<valueHelp>
<format>static</format>
<description>STATIC Spatial Multiplexing (SM) Power Save</description>
</valueHelp>
<valueHelp>
<format>dynamic</format>
<description>DYNAMIC Spatial Multiplexing (SM) Power Save</description>
</valueHelp>
<constraint>
<regex>(static|dynamic)</regex>
</constraint>
</properties>
</leafNode>
<node name="stbc">
<properties>
<help>Support for sending and receiving PPDU using STBC (Space Time Block Coding)</help>
</properties>
<children>
<leafNode name="rx">
<properties>
<help>Enable receiving PPDU using STBC (Space Time Block Coding)</help>
<valueHelp>
<format>[1-3]+</format>
<description>Number of spacial streams that can use RX STBC</description>
</valueHelp>
<constraint>
<regex>[1-3]+</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="tx">
<properties>
<help>Enable sending PPDU using STBC (Space Time Block Coding)</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<leafNode name="require-ht">
<properties>
<help>Require stations to support HT PHY</help>
<valueless/>
</properties>
</leafNode>
<node name="vht">
<properties>
<help>Very High Throughput (VHT) settings</help>
</properties>
<children>
<leafNode name="antenna-count">
<properties>
<help>Number of antennas on this card</help>
<valueHelp>
<format>u32:1-8</format>
<description>Number of antennas for this card</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-8"/>
</constraint>
</properties>
</leafNode>
<leafNode name="antenna-pattern-fixed">
<properties>
<help>Set if antenna pattern does not change during the lifetime of an association</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="beamform">
<properties>
<help>VHT beamforming capabilities</help>
<completionHelp>
<list>single-user-beamformer single-user-beamformee multi-user-beamformer multi-user-beamformee</list>
</completionHelp>
<valueHelp>
<format>single-user-beamformer</format>
<description>Support for operation as single user beamformer</description>
</valueHelp>
<valueHelp>
<format>single-user-beamformee</format>
<description>Support for operation as single user beamformee</description>
</valueHelp>
<valueHelp>
<format>multi-user-beamformer</format>
<description>Support for operation as multi user beamformer</description>
</valueHelp>
<valueHelp>
<format>multi-user-beamformee</format>
<description>Support for operation as multi user beamformee</description>
</valueHelp>
<constraint>
<regex>(single-user-beamformer|single-user-beamformee|multi-user-beamformer|multi-user-beamformee)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<node name="center-channel-freq">
<properties>
<help>VHT operating channel center frequency</help>
</properties>
<children>
<leafNode name="freq-1">
<properties>
<help>VHT operating channel center frequency - center freq 1 (for use with 80, 80+80 and 160 modes)</help>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 a/h/j/n/ac) center channel index (use 42 for primary 80MHz channel 36)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 34-173"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 34 and 173</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="freq-2">
<properties>
<help>VHT operating channel center frequency - center freq 2 (for use with the 80+80 mode)</help>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 ac) center channel index (use 58 for secondary 80MHz channel 52)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 34-173"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 34 and 173</constraintErrorMessage>
</properties>
</leafNode>
</children>
</node>
<leafNode name="channel-set-width">
<properties>
<help>VHT operating Channel width</help>
<completionHelp>
<list>0 1 2 3</list>
</completionHelp>
<valueHelp>
<format>0</format>
<description>20 or 40 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>1</format>
<description>80 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>2</format>
<description>160 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>3</format>
<description>80+80 MHz channel width</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-3"/>
</constraint>
</properties>
</leafNode>
<leafNode name="ldpc">
<properties>
<help>Enable LDPC (Low Density Parity Check) coding capability</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="link-adaptation">
<properties>
<help>VHT link adaptation capabilities</help>
<completionHelp>
<list>unsolicited both</list>
</completionHelp>
<valueHelp>
<format>unsolicited</format>
<description>Station provides only unsolicited VHT MFB</description>
</valueHelp>
<valueHelp>
<format>both</format>
<description>Station can provide VHT MFB in response to VHT MRQ and unsolicited VHT MFB</description>
</valueHelp>
<constraint>
<regex>(unsolicited|both)</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="max-mpdu-exp">
<properties>
<help>Set the maximum length of A-MPDU pre-EOF padding that the station can receive</help>
<valueHelp>
<format>u32:0-7</format>
<description>Maximum length of A-MPDU pre-EOF padding = 2 pow(13 + x) -1 octets</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-7"/>
</constraint>
</properties>
</leafNode>
<leafNode name="max-mpdu">
<properties>
<help>Increase Maximum MPDU length to 7991 or 11454 octets (otherwise: 3895 octets)</help>
<completionHelp>
<list>7991 11454</list>
</completionHelp>
<valueHelp>
<format>7991</format>
<description>ncrease Maximum MPDU length to 7991 octets</description>
</valueHelp>
<valueHelp>
<format>11454</format>
<description>ncrease Maximum MPDU length to 11454 octets</description>
</valueHelp>
<constraint>
<regex>(7991|11454)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="short-gi">
<properties>
<help>Short GI capabilities</help>
<completionHelp>
<list>80 160</list>
</completionHelp>
<valueHelp>
<format>80</format>
<description>Short GI for 80 MHz</description>
</valueHelp>
<valueHelp>
<format>160</format>
<description>Short GI for 160 MHz</description>
</valueHelp>
<constraint>
<regex>(80|160)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
<node name="stbc">
<properties>
<help>Support for sending and receiving PPDU using STBC (Space Time Block Coding)</help>
</properties>
<children>
<leafNode name="rx">
<properties>
<help>Enable receiving PPDU using STBC (Space Time Block Coding)</help>
<valueHelp>
<format>[1-4]+</format>
<description>Number of spacial streams that can use RX STBC</description>
</valueHelp>
<constraint>
<regex>[1-4]+</regex>
</constraint>
<constraintErrorMessage>Invalid capability item</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="tx">
<properties>
<help>Enable sending PPDU using STBC (Space Time Block Coding)</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="tx-powersave">
<properties>
<help>Enable VHT TXOP Power Save Mode</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="vht-cf">
<properties>
<help>Station supports receiving VHT variant HT Control field</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="require-vht">
<properties>
<help>Require stations to support VHT PHY</help>
<valueless/>
</properties>
</leafNode>
<node name="he">
<properties>
<help>High Efficiency (HE) settings</help>
</properties>
<children>
<leafNode name="channel-set-width">
<properties>
<help>HE operating channel width</help>
<completionHelp>
<!--
op_modes drawn from:
https://w1.fi/cgit/hostap/tree/src/common/ieee802_11_common.c?id=195cc3d919503fb0d699d9a56a58a72602b25f51#n1525
802.11ax (WiFi-6e - HE) can use up to 160MHz bandwidth channels
-->
<list>131 132 133 134 135</list>
</completionHelp>
<valueHelp>
<format>131</format>
<description>20 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>132</format>
<description>40 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>133</format>
<description>80 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>134</format>
<description>160 MHz channel width</description>
</valueHelp>
<valueHelp>
<format>135</format>
<description>80+80 MHz channel width</description>
</valueHelp>
<constraint>
<regex>(131|132|133|134|135)</regex>
</constraint>
</properties>
</leafNode>
<node name="center-channel-freq">
<properties>
<help>HE operating channel center frequency</help>
</properties>
<children>
<leafNode name="freq-1">
<properties>
<help>HE operating channel center frequency - center freq 1 (for use with 80, 80+80 and 160 modes)</help>
<valueHelp>
<format>u32:1-233</format>
<description>6Ghz (802.11 ax) center channel index (use 3 (at 40MHz), 7 (at 80MHz) or 15 (at 160MHz) for primary channel 1)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-233"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 1 and 233</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="freq-2">
<properties>
<help>HE operating channel center frequency - center freq 2 (for use with the 80+80 mode)</help>
<valueHelp>
<format>u32:1-233</format>
<description>6Ghz (802.11 ax) center channel index (use 23 (at 80MHz) for secondary channel 17)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-233"/>
</constraint>
<constraintErrorMessage>Channel center value must be between 1 and 233</constraintErrorMessage>
</properties>
</leafNode>
</children>
</node>
<leafNode name="antenna-pattern-fixed">
<properties>
<help>Tell the AP that antenna positions are fixed and will not change during the lifetime of an association</help>
<valueless/>
</properties>
</leafNode>
<node name="beamform">
<properties>
<help>HE beamforming capabilities</help>
</properties>
<children>
<leafNode name="single-user-beamformer">
<properties>
<help>Support for operation as single user beamformer</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="single-user-beamformee">
<properties>
<help>Support for operation as single user beamformee</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="multi-user-beamformer">
<properties>
<help>Support for operation as multi user beamformer</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="bss-color">
<properties>
<help>BSS coloring helps to prevent channel jamming when multiple APs use the same channels</help>
<constraint>
<validator name="numeric" argument="--range 1-63"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="require-he">
<properties>
<help>Require stations to support HE PHY</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="channel">
<properties>
<help>Wireless radio channel</help>
<valueHelp>
<format>0</format>
<description>Automatic Channel Selection (ACS)</description>
</valueHelp>
<valueHelp>
<format>u32:1-14</format>
<description>2.4Ghz (802.11 b/g/n) Channel</description>
</valueHelp>
<valueHelp>
<format>u32:34-173</format>
<description>5Ghz (802.11 a/h/j/n/ac) Channel</description>
</valueHelp>
<valueHelp>
<format>u32:1-233</format>
<description>6Ghz (802.11 ax) Channel</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-0 --range 1-14 --range 34-173 --range 1-233"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
- <leafNode name="country-code">
- <properties>
- <help>Indicate country in which device is operating</help>
- <completionHelp>
- <list>00 ad ae af ai al am an ar as at au aw az ba bb bd be bf bg bh bl bm bn bo br bs bt by bz ca cf ch ci cl cn co cr cu cx cy cz de dk dm do dz ec ee eg es et fi fm fr gb gd ge gf gh gl gp gr gt gu gy hk hn hr ht hu id ie il in ir is it jm jo jp ke kh kn kp kr kw ky kz lb lc li lk ls lt lu lv ma mc md me mf mh mk mn mo mp mq mr mt mu mv mw mx my ng ni nl no np nz om pa pe pf pg ph pk pl pm pr pt pw py qa re ro rs ru rw sa se sg si sk sn sr sv sy tc td tg th tn tr tt tw tz ua ug us uy uz vc ve vi vn vu wf ws ye yt za zw</list>
- </completionHelp>
- <valueHelp>
- <format>00</format>
- <description>World regulatory domain</description>
- </valueHelp>
- <valueHelp>
- <format>txt</format>
- <description>ISO/IEC 3166-1 Country Code</description>
- </valueHelp>
- <constraint>
- <regex>(00|ad|ae|af|ai|al|am|an|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bl|bm|bn|bo|br|bs|bt|by|bz|ca|cf|ch|ci|cl|cn|co|cr|cu|cx|cy|cz|de|dk|dm|do|dz|ec|ee|eg|es|et|fi|fm|fr|gb|gd|ge|gf|gh|gl|gp|gr|gt|gu|gy|hk|hn|hr|ht|hu|id|ie|il|in|ir|is|it|jm|jo|jp|ke|kh|kn|kp|kr|kw|ky|kz|lb|lc|li|lk|ls|lt|lu|lv|ma|mc|md|me|mf|mh|mk|mn|mo|mp|mq|mr|mt|mu|mv|mw|mx|my|ng|ni|nl|no|np|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pr|pt|pw|py|qa|re|ro|rs|ru|rw|sa|se|sg|si|sk|sn|sr|sv|sy|tc|td|tg|th|tn|tr|tt|tw|tz|ua|ug|us|uy|uz|vc|ve|vi|vn|vu|wf|ws|ye|yt|za|zw)</regex>
- </constraint>
- <constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage>
- </properties>
- </leafNode>
#include <include/generic-description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
<leafNode name="disable-broadcast-ssid">
<properties>
<help>Disable broadcast of SSID from access-point</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/disable-link-detect.xml.i>
#include <include/interface/disable.xml.i>
#include <include/interface/vrf.xml.i>
<leafNode name="expunge-failing-stations">
<properties>
<help>Disassociate stations based on excessive transmission failures</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/ipv4-options.xml.i>
#include <include/interface/ipv6-options.xml.i>
#include <include/interface/hw-id.xml.i>
<leafNode name="isolate-stations">
<properties>
<help>Isolate stations on the AP so they cannot see each other</help>
<valueless/>
</properties>
</leafNode>
#include <include/interface/mac.xml.i>
<leafNode name="max-stations">
<properties>
<help>Maximum number of wireless radio stations. Excess stations will be rejected upon authentication request.</help>
<valueHelp>
<format>u32:1-2007</format>
<description>Number of allowed stations</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-2007"/>
</constraint>
<constraintErrorMessage>Number of stations must be between 1 and 2007</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="stationary-ap">
<properties>
<help>Stationary AP config indicates that the AP doesn't move.</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="mgmt-frame-protection">
<properties>
<help>Management Frame Protection (MFP) according to IEEE 802.11w</help>
<completionHelp>
<list>disabled optional required</list>
</completionHelp>
<valueHelp>
<format>disabled</format>
<description>no MFP</description>
</valueHelp>
<valueHelp>
<format>optional</format>
<description>MFP optional</description>
</valueHelp>
<valueHelp>
<format>required</format>
<description>MFP enforced (mandatory for WPA3)</description>
</valueHelp>
<constraint>
<regex>(disabled|optional|required)</regex>
</constraint>
</properties>
<defaultValue>disabled</defaultValue>
</leafNode>
<leafNode name="enable-bf-protection">
<properties>
<help>Beacon Protection: management frame protection for Beacon frames, requires Management Frame Protection (MFP)</help>
<valueless/>
</properties>
<defaultValue>disabled</defaultValue>
</leafNode>
<leafNode name="mode">
<properties>
<help>Wireless radio mode</help>
<completionHelp>
<list>a b g n ac ax</list>
</completionHelp>
<valueHelp>
<format>a</format>
<description>802.11a - 54 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>b</format>
<description>802.11b - 11 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>g</format>
<description>802.11g - 54 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>n</format>
<description>802.11n - 600 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>ac</format>
<description>802.11ac - 1300 Mbits/sec</description>
</valueHelp>
<valueHelp>
<format>ax</format>
<description>802.11ax (6GHz only for now)</description>
</valueHelp>
<constraint>
<regex>(a|b|g|n|ac|ax)</regex>
</constraint>
</properties>
<defaultValue>g</defaultValue>
</leafNode>
<!-- background_radar_detection not yet supported by VyOS's hostapd
<leafNode name="background-radar-detection">
<properties>
<help>Enabling background radar detection feature allows CAC to be run on dedicated radio RF chains while the radio(s) are otherwise running normal AP activities on other channels.</help>
<valueless/>
</properties>
</leafNode>
-->
#include <include/interface/mirror.xml.i>
<leafNode name="physical-device">
<properties>
<help>Wireless physical device</help>
<completionHelp>
<script>${vyos_completion_dir}/list_wireless_phys.sh</script>
</completionHelp>
<constraint>
<validator name="wireless-phy"/>
</constraint>
</properties>
<defaultValue>phy0</defaultValue>
</leafNode>
<leafNode name="reduce-transmit-power">
<properties>
<help>Transmission power reduction in dBm</help>
<valueHelp>
<format>u32:0-255</format>
<description>TX power reduction in dBm</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
<constraintErrorMessage>dBm value must be between 0 and 255</constraintErrorMessage>
</properties>
</leafNode>
<node name="security">
<properties>
<help>Wireless security settings</help>
</properties>
<children>
<node name="station-address">
<properties>
<help>Station MAC address based authentication</help>
</properties>
<children>
<leafNode name="mode">
<properties>
<help>Select security operation mode</help>
<completionHelp>
<list>accept deny</list>
</completionHelp>
<valueHelp>
<format>accept</format>
<description>Accept all clients unless found in deny list</description>
</valueHelp>
<valueHelp>
<format>deny</format>
<description>Deny all clients unless found in accept list</description>
</valueHelp>
<constraint>
<regex>(accept|deny)</regex>
</constraint>
</properties>
<defaultValue>accept</defaultValue>
</leafNode>
<node name="accept">
<properties>
<help>Accept station MAC address</help>
</properties>
<children>
#include <include/interface/mac-multi.xml.i>
</children>
</node>
<node name="deny">
<properties>
<help>Deny station MAC address</help>
</properties>
<children>
#include <include/interface/mac-multi.xml.i>
</children>
</node>
</children>
</node>
<node name="wep">
<properties>
<help>Wired Equivalent Privacy (WEP) parameters</help>
</properties>
<children>
<leafNode name="key">
<properties>
<help>WEP encryption key</help>
<valueHelp>
<format>txt</format>
<description>Wired Equivalent Privacy key</description>
</valueHelp>
<constraint>
<regex>([a-fA-F0-9]{10}|[a-fA-F0-9]{26}|[a-fA-F0-9]{32})</regex>
</constraint>
<constraintErrorMessage>Invalid WEP key</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
</children>
</node>
<node name="wpa">
<properties>
<help>Wifi Protected Access (WPA) parameters</help>
</properties>
<children>
<leafNode name="cipher">
<properties>
<help>Cipher suite for WPA unicast packets</help>
<completionHelp>
<list>GCMP-256 GCMP CCMP-256 CCMP TKIP</list>
</completionHelp>
<valueHelp>
<format>GCMP-256</format>
<description>AES in Galois/counter mode with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>GCMP</format>
<description>AES in Galois/counter mode with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP-256</format>
<description>AES in Counter mode with CBC-MAC with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP</format>
<description>AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] (supported on all WPA2 APs)</description>
</valueHelp>
<valueHelp>
<format>TKIP</format>
<description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description>
</valueHelp>
<constraint>
<regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex>
</constraint>
<constraintErrorMessage>Invalid cipher selection</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
<leafNode name="group-cipher">
<properties>
<help>Cipher suite for WPA multicast and broadcast packets</help>
<completionHelp>
<list>GCMP-256 GCMP CCMP-256 CCMP TKIP</list>
</completionHelp>
<valueHelp>
<format>GCMP-256</format>
<description>AES in Galois/counter mode with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>GCMP</format>
<description>AES in Galois/counter mode with 128-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP-256</format>
<description>AES in Counter mode with CBC-MAC with 256-bit key</description>
</valueHelp>
<valueHelp>
<format>CCMP</format>
<description>AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] (supported on all WPA2 APs)</description>
</valueHelp>
<valueHelp>
<format>TKIP</format>
<description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description>
</valueHelp>
<constraint>
<regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex>
</constraint>
<constraintErrorMessage>Invalid group cipher selection</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="group-mgmt-cipher">
<properties>
<help>Group management cipher suite. All the stations connecting to the BSS will also need to support the selected cipher</help>
<completionHelp>
<list>AES-128-CMAC BIP-CMAC-256 BIP-GMAC-128 BIP-GMAC-256</list>
</completionHelp>
<constraint>
<regex>(AES-128-CMAC|BIP-CMAC-256|BIP-GMAC-128|BIP-GMAC-256)</regex>
</constraint>
<constraintErrorMessage>Invalid group management cipher selection</constraintErrorMessage>
</properties>
<defaultValue>AES-128-CMAC</defaultValue>
</leafNode>
<leafNode name="mode">
<properties>
<help>WPA mode</help>
<completionHelp>
<list>wpa wpa2 wpa+wpa2 wpa3</list>
</completionHelp>
<valueHelp>
<format>wpa</format>
<description>WPA (IEEE 802.11i/D3.0)</description>
</valueHelp>
<valueHelp>
<format>wpa2</format>
<description>WPA2 (full IEEE 802.11i/RSN)</description>
</valueHelp>
<valueHelp>
<format>wpa+wpa2</format>
<description>Allow both WPA and WPA2</description>
</valueHelp>
<valueHelp>
<format>wpa3</format>
<description>WPA3 (required for 802.11ax, you must also set mgmt-frame-protection as required)</description>
</valueHelp>
<constraint>
<regex>(wpa|wpa2|wpa\+wpa2|wpa3)</regex>
</constraint>
<constraintErrorMessage>Unknown WPA mode</constraintErrorMessage>
</properties>
<defaultValue>wpa+wpa2</defaultValue>
</leafNode>
<leafNode name="passphrase">
<properties>
<help>WPA personal shared pass phrase. If you are using special characters in the WPA passphrase then single quotes are required.</help>
<valueHelp>
<format>txt</format>
<description>Passphrase of at least 8 but not more than 63 printable characters</description>
</valueHelp>
<constraint>
<regex>.{8,63}</regex>
</constraint>
<constraintErrorMessage>Invalid WPA pass phrase, must be 8 to 63 printable characters!</constraintErrorMessage>
</properties>
</leafNode>
#include <include/radius-auth-server-ipv4.xml.i>
<node name="radius">
<children>
<tagNode name="server">
<children>
<leafNode name="accounting">
<properties>
<help>Enable RADIUS server to receive accounting info</help>
<valueless/>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
</children>
</node>
</children>
</node>
<leafNode name="ssid">
<properties>
<help>Wireless access-point service set identifier (SSID)</help>
<constraint>
<regex>.{1,32}</regex>
</constraint>
<constraintErrorMessage>Invalid SSID</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="type">
<properties>
<help>Wireless device type for this interface</help>
<completionHelp>
<list>access-point station monitor</list>
</completionHelp>
<valueHelp>
<format>access-point</format>
<description>Access-point forwards packets between other nodes</description>
</valueHelp>
<valueHelp>
<format>station</format>
<description>Connects to another access point</description>
</valueHelp>
<valueHelp>
<format>monitor</format>
<description>Passively monitor all packets on the frequency/channel</description>
</valueHelp>
<constraint>
<regex>(access-point|station|monitor)</regex>
</constraint>
<constraintErrorMessage>Type must be access-point, station or monitor</constraintErrorMessage>
</properties>
<defaultValue>monitor</defaultValue>
</leafNode>
#include <include/interface/per-client-thread.xml.i>
#include <include/interface/redirect.xml.i>
#include <include/interface/vif.xml.i>
#include <include/interface/vif-s.xml.i>
</children>
</tagNode>
</children>
</node>
</interfaceDefinition>
diff --git a/interface-definitions/system_wireless.xml.in b/interface-definitions/system_wireless.xml.in
new file mode 100644
index 000000000..834f8b624
--- /dev/null
+++ b/interface-definitions/system_wireless.xml.in
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="system">
+ <children>
+ <node name="wireless" owner="${vyos_conf_scripts_dir}/system_wireless.py">
+ <properties>
+ <help>Wireless (IEEE-802.11) subsystem settings</help>
+ <!-- must be before interface wireless, check /opt/vyatta/sbin/priority.pl -->
+ <priority>317</priority>
+ </properties>
+ <children>
+ <leafNode name="country-code">
+ <properties>
+ <help>Indicate country in which device is operating</help>
+ <completionHelp>
+ <list>00 ad ae af ai al am an ar as at au aw az ba bb bd be bf bg bh bl bm bn bo br bs bt by bz ca cf ch ci cl cn co cr cu cx cy cz de dk dm do dz ec ee eg es et fi fm fr gb gd ge gf gh gl gp gr gt gu gy hk hn hr ht hu id ie il in ir is it jm jo jp ke kh kn kp kr kw ky kz lb lc li lk ls lt lu lv ma mc md me mf mh mk mn mo mp mq mr mt mu mv mw mx my ng ni nl no np nz om pa pe pf pg ph pk pl pm pr pt pw py qa re ro rs ru rw sa se sg si sk sn sr sv sy tc td tg th tn tr tt tw tz ua ug us uy uz vc ve vi vn vu wf ws ye yt za zw</list>
+ </completionHelp>
+ <valueHelp>
+ <format>00</format>
+ <description>World regulatory domain</description>
+ </valueHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>ISO/IEC 3166-1 Country Code</description>
+ </valueHelp>
+ <constraint>
+ <regex>(00|ad|ae|af|ai|al|am|an|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bl|bm|bn|bo|br|bs|bt|by|bz|ca|cf|ch|ci|cl|cn|co|cr|cu|cx|cy|cz|de|dk|dm|do|dz|ec|ee|eg|es|et|fi|fm|fr|gb|gd|ge|gf|gh|gl|gp|gr|gt|gu|gy|hk|hn|hr|ht|hu|id|ie|il|in|ir|is|it|jm|jo|jp|ke|kh|kn|kp|kr|kw|ky|kz|lb|lc|li|lk|ls|lt|lu|lv|ma|mc|md|me|mf|mh|mk|mn|mo|mp|mq|mr|mt|mu|mv|mw|mx|my|ng|ni|nl|no|np|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pr|pt|pw|py|qa|re|ro|rs|ru|rw|sa|se|sg|si|sk|sn|sr|sv|sy|tc|td|tg|th|tn|tr|tt|tw|tz|ua|ug|us|uy|uz|vc|ve|vi|vn|vu|wf|ws|ye|yt|za|zw)</regex>
+ </constraint>
+ <constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/smoketest/config-tests/wireless-basic b/smoketest/config-tests/wireless-basic
new file mode 100644
index 000000000..5d7bc8aaa
--- /dev/null
+++ b/smoketest/config-tests/wireless-basic
@@ -0,0 +1,25 @@
+set interfaces ethernet eth0 duplex 'auto'
+set interfaces ethernet eth0 speed 'auto'
+set interfaces ethernet eth1 duplex 'auto'
+set interfaces ethernet eth1 speed 'auto'
+set interfaces wireless wlan0 address '192.168.0.1/24'
+set interfaces wireless wlan0 channel '1'
+set interfaces wireless wlan0 mode 'n'
+set interfaces wireless wlan0 security wpa cipher 'CCMP'
+set interfaces wireless wlan0 security wpa mode 'wpa2'
+set interfaces wireless wlan0 security wpa passphrase '12345678'
+set interfaces wireless wlan0 ssid 'VyOS'
+set interfaces wireless wlan0 type 'access-point'
+set interfaces wireless wlan1 address '192.168.1.1/24'
+set interfaces wireless wlan1 channel '2'
+set interfaces wireless wlan1 mode 'n'
+set interfaces wireless wlan1 ssid 'VyOS-PUBLIC'
+set interfaces wireless wlan1 type 'access-point'
+set system config-management commit-revisions '200'
+set system console device ttyS0 speed 115200
+set system domain-name 'dev.vyos.net'
+set system host-name 'WR1'
+set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0'
+set system wireless country-code 'es'
+set system syslog global facility all level 'info'
+set system syslog global facility local7 level 'debug'
diff --git a/smoketest/configs/wireless-basic b/smoketest/configs/wireless-basic
new file mode 100644
index 000000000..9cc34f5bc
--- /dev/null
+++ b/smoketest/configs/wireless-basic
@@ -0,0 +1,66 @@
+interfaces {
+ ethernet eth0 {
+ duplex "auto"
+ speed "auto"
+ }
+ ethernet eth1 {
+ duplex "auto"
+ speed "auto"
+ }
+ wireless wlan0 {
+ address 192.168.0.1/24
+ channel 1
+ country-code es
+ mode n
+ security {
+ wpa {
+ cipher CCMP
+ mode wpa2
+ passphrase 12345678
+ }
+ }
+ ssid VyOS
+ type access-point
+ }
+ wireless wlan1 {
+ address 192.168.1.1/24
+ channel 2
+ country-code de
+ mode n
+ ssid VyOS-PUBLIC
+ type access-point
+ }
+}
+system {
+ config-management {
+ commit-revisions "200"
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ domain-name "dev.vyos.net"
+ host-name "WR1"
+ login {
+ user vyos {
+ authentication {
+ encrypted-password "$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0"
+ }
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level "info"
+ }
+ facility local7 {
+ level "debug"
+ }
+ }
+ }
+}
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "bgp@5:broadcast-relay@1:cluster@2:config-management@1:conntrack@5:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@8:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:reverse-proxy@1:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2"
+// Release version: 1.4.0
diff --git a/src/conf_mode/interfaces_wireless.py b/src/conf_mode/interfaces_wireless.py
index 9488f6797..aa65adc10 100755
--- a/src/conf_mode/interfaces_wireless.py
+++ b/src/conf_mode/interfaces_wireless.py
@@ -1,330 +1,337 @@
#!/usr/bin/env python3
#
# Copyright (C) 2019-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from sys import exit
from re import findall
from netaddr import EUI, mac_unix_expanded
from time import sleep
from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configdict import dict_merge
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
from vyos.configverify import verify_mirror_redirect
from vyos.configverify import verify_vlan_config
from vyos.configverify import verify_vrf
from vyos.configverify import verify_bond_bridge_member
from vyos.ifconfig import WiFiIf
from vyos.template import render
from vyos.utils.dict import dict_search
from vyos.utils.kernel import check_kmod
from vyos.utils.process import call
from vyos.utils.process import is_systemd_service_active
from vyos.utils.process import is_systemd_service_running
from vyos.utils.network import interface_exists
from vyos import ConfigError
from vyos import airbag
airbag.enable()
# XXX: wpa_supplicant works on the source interface
wpa_suppl_conf = '/run/wpa_supplicant/{ifname}.conf'
hostapd_conf = '/run/hostapd/{ifname}.conf'
hostapd_accept_station_conf = '/run/hostapd/{ifname}_station_accept.conf'
hostapd_deny_station_conf = '/run/hostapd/{ifname}_station_deny.conf'
+country_code_path = ['system', 'wireless', 'country-code']
+
def find_other_stations(conf, base, ifname):
"""
Only one wireless interface per phy can be in station mode -
find all interfaces attached to a phy which run in station mode
"""
old_level = conf.get_level()
conf.set_level(base)
dict = {}
for phy in os.listdir('/sys/class/ieee80211'):
list = []
for interface in conf.list_nodes([]):
if interface == ifname:
continue
# the following node is mandatory
if conf.exists([interface, 'physical-device', phy]):
tmp = conf.return_value([interface, 'type'])
if tmp == 'station':
list.append(interface)
if list:
dict.update({phy: list})
conf.set_level(old_level)
return dict
def get_config(config=None):
"""
Retrive CLI config as dictionary. Dictionary can never be empty, as at least the
interface name will be added or a deleted flag
"""
if config:
conf = config
else:
conf = Config()
base = ['interfaces', 'wireless']
- ifname, wifi = get_interface_dict(conf, base)
+ _, wifi = get_interface_dict(conf, base)
+
+ # retrieve global Wireless regulatory domain setting
+ if conf.exists(country_code_path):
+ wifi['country_code'] = conf.return_value(country_code_path)
if 'deleted' not in wifi:
# then get_interface_dict provides default keys
if wifi.from_defaults(['security', 'wep']): # if not set by user
del wifi['security']['wep']
if wifi.from_defaults(['security', 'wpa']): # if not set by user
del wifi['security']['wpa']
# XXX: Jinja2 can not operate on a dictionary key when it starts of with a number
if '40mhz_incapable' in (dict_search('capabilities.ht', wifi) or []):
wifi['capabilities']['ht']['fourtymhz_incapable'] = wifi['capabilities']['ht']['40mhz_incapable']
del wifi['capabilities']['ht']['40mhz_incapable']
if dict_search('security.wpa', wifi) != None:
wpa_cipher = wifi['security']['wpa'].get('cipher')
wpa_mode = wifi['security']['wpa'].get('mode')
if not wpa_cipher:
tmp = None
if wpa_mode == 'wpa':
tmp = {'security': {'wpa': {'cipher' : ['TKIP', 'CCMP']}}}
elif wpa_mode == 'wpa2':
tmp = {'security': {'wpa': {'cipher' : ['CCMP']}}}
elif wpa_mode == 'both':
tmp = {'security': {'wpa': {'cipher' : ['CCMP', 'TKIP']}}}
elif wpa_mode == 'wpa3':
# According to WiFi specs (https://www.wi-fi.org/file/wpa3-specification)
# section 3.5: WPA3-Enterprise 192-bit mode
# WiFi NICs which would be able to connect to WPA3-Enterprise managed
# networks MUST support GCMP-256.
# Reasoning: Provided that chipsets would most likely _not_ be
# "private user only", they all would come with built-in support
# for GCMP-256.
tmp = {'security': {'wpa': {'cipher' : ['CCMP', 'CCMP-256', 'GCMP', 'GCMP-256']}}}
if tmp: wifi = dict_merge(tmp, wifi)
# Only one wireless interface per phy can be in station mode
tmp = find_other_stations(conf, base, wifi['ifname'])
if tmp: wifi['station_interfaces'] = tmp
# used in hostapd.conf.j2
wifi['hostapd_accept_station_conf'] = hostapd_accept_station_conf.format(**wifi)
wifi['hostapd_deny_station_conf'] = hostapd_deny_station_conf.format(**wifi)
return wifi
def verify(wifi):
if 'deleted' in wifi:
verify_bridge_delete(wifi)
return None
if 'physical_device' not in wifi:
raise ConfigError('You must specify a physical-device "phy"')
physical_device = wifi['physical_device']
if not os.path.exists(f'/sys/class/ieee80211/{physical_device}'):
raise ConfigError(f'Wirelss interface PHY "{physical_device}" does not exist!')
if 'type' not in wifi:
raise ConfigError('You must specify a WiFi mode')
if 'ssid' not in wifi and wifi['type'] != 'monitor':
raise ConfigError('SSID must be configured unless type is set to "monitor"!')
if wifi['type'] == 'access-point':
if 'country_code' not in wifi:
- raise ConfigError('Wireless country-code is mandatory')
+ raise ConfigError(f'Wireless country-code is mandatory, use: '\
+ f'"set {" ".join(country_code_path)}"!')
if 'channel' not in wifi:
raise ConfigError('Wireless channel must be configured!')
if 'capabilities' in wifi and 'he' in wifi['capabilities']:
if 'channel_set_width' not in wifi['capabilities']['he']:
raise ConfigError('Channel width must be configured!')
# op_modes drawn from:
# https://w1.fi/cgit/hostap/tree/src/common/ieee802_11_common.c?id=195cc3d919503fb0d699d9a56a58a72602b25f51#n1525
# 802.11ax (WiFi-6e - HE) can use up to 160MHz bandwidth channels
six_ghz_op_modes_he = ['131', '132', '133', '134', '135']
# 802.11be (WiFi-7 - EHT) can use up to 320MHz bandwidth channels
six_ghz_op_modes_eht = six_ghz_op_modes_he.append('137')
if 'security' in wifi and 'wpa' in wifi['security'] and 'mode' in wifi['security']['wpa']:
if wifi['security']['wpa']['mode'] == 'wpa3':
if 'he' in wifi['capabilities']:
if wifi['capabilities']['he']['channel_set_width'] in six_ghz_op_modes_he:
if 'mgmt_frame_protection' not in wifi or wifi['mgmt_frame_protection'] != 'required':
raise ConfigError('Management Frame Protection (MFP) is required with WPA3 at 6GHz! Consider also enabling Beacon Frame Protection (BFP) if your device supports it.')
if 'security' in wifi:
if {'wep', 'wpa'} <= set(wifi.get('security', {})):
raise ConfigError('Must either use WEP or WPA security!')
if 'wep' in wifi['security']:
if 'key' in wifi['security']['wep'] and len(wifi['security']['wep']) > 4:
raise ConfigError('No more then 4 WEP keys configurable')
elif 'key' not in wifi['security']['wep']:
raise ConfigError('Security WEP configured - missing WEP keys!')
elif 'wpa' in wifi['security']:
wpa = wifi['security']['wpa']
if not any(i in ['passphrase', 'radius'] for i in wpa):
raise ConfigError('Misssing WPA key or RADIUS server')
if 'radius' in wpa:
if 'server' in wpa['radius']:
for server in wpa['radius']['server']:
if 'key' not in wpa['radius']['server'][server]:
raise ConfigError(f'Misssing RADIUS shared secret key for server: {server}')
if 'capabilities' in wifi:
capabilities = wifi['capabilities']
if 'vht' in capabilities:
if 'ht' not in capabilities:
raise ConfigError('Specify HT flags if you want to use VHT!')
if {'beamform', 'antenna_count'} <= set(capabilities.get('vht', {})):
if capabilities['vht']['antenna_count'] == '1':
raise ConfigError('Cannot use beam forming with just one antenna!')
if capabilities['vht']['beamform'] == 'single-user-beamformer':
if int(capabilities['vht']['antenna_count']) < 3:
# Nasty Gotcha: see lines 708-721 in:
# https://w1.fi/cgit/hostap/tree/hostapd/hostapd.conf?h=hostap_2_10&id=cff80b4f7d3c0a47c052e8187d671710f48939e4#n708
raise ConfigError('Single-user beam former requires at least 3 antennas!')
if 'station_interfaces' in wifi and wifi['type'] == 'station':
phy = wifi['physical_device']
if phy in wifi['station_interfaces']:
if len(wifi['station_interfaces'][phy]) > 0:
raise ConfigError('Only one station per wireless physical interface possible!')
verify_address(wifi)
verify_vrf(wifi)
verify_bond_bridge_member(wifi)
verify_mirror_redirect(wifi)
# use common function to verify VLAN configuration
verify_vlan_config(wifi)
return None
def generate(wifi):
check_kmod('mac80211')
interface = wifi['ifname']
# Delete config files if interface is removed
if 'deleted' in wifi:
if os.path.isfile(hostapd_conf.format(**wifi)):
os.unlink(hostapd_conf.format(**wifi))
if os.path.isfile(hostapd_accept_station_conf.format(**wifi)):
os.unlink(hostapd_accept_station_conf.format(**wifi))
if os.path.isfile(hostapd_deny_station_conf.format(**wifi)):
os.unlink(hostapd_deny_station_conf.format(**wifi))
if os.path.isfile(wpa_suppl_conf.format(**wifi)):
os.unlink(wpa_suppl_conf.format(**wifi))
return None
if 'mac' not in wifi:
# http://wiki.stocksy.co.uk/wiki/Multiple_SSIDs_with_hostapd
# generate locally administered MAC address from used phy interface
with open('/sys/class/ieee80211/{physical_device}/addresses'.format(**wifi), 'r') as f:
# some PHYs tend to have multiple interfaces and thus supply multiple MAC
# addresses - we only need the first one for our calculation
tmp = f.readline().rstrip()
tmp = EUI(tmp).value
# mask last nibble from the MAC address
tmp &= 0xfffffffffff0
# set locally administered bit in MAC address
tmp |= 0x020000000000
# we now need to add an offset to our MAC address indicating this
# subinterfaces index
tmp += int(findall(r'\d+', interface)[0])
# convert integer to "real" MAC address representation
mac = EUI(hex(tmp).split('x')[-1])
# change dialect to use : as delimiter instead of -
mac.dialect = mac_unix_expanded
wifi['mac'] = str(mac)
# render appropriate new config files depending on access-point or station mode
if wifi['type'] == 'access-point':
render(hostapd_conf.format(**wifi), 'wifi/hostapd.conf.j2', wifi)
render(hostapd_accept_station_conf.format(**wifi), 'wifi/hostapd_accept_station.conf.j2', wifi)
render(hostapd_deny_station_conf.format(**wifi), 'wifi/hostapd_deny_station.conf.j2', wifi)
elif wifi['type'] == 'station':
render(wpa_suppl_conf.format(**wifi), 'wifi/wpa_supplicant.conf.j2', wifi)
return None
def apply(wifi):
interface = wifi['ifname']
# From systemd source code:
# If there's a stop job queued before we enter the DEAD state, we shouldn't act on Restart=,
# in order to not undo what has already been enqueued. */
#
# It was found that calling restart on hostapd will (4 out of 10 cases) deactivate
# the service instead of restarting it, when it was not yet properly stopped
# systemd[1]: hostapd@wlan1.service: Deactivated successfully.
# Thus kill all WIFI service and start them again after it's ensured nothing lives
call(f'systemctl stop hostapd@{interface}.service')
call(f'systemctl stop wpa_supplicant@{interface}.service')
if 'deleted' in wifi:
WiFiIf(**wifi).remove()
return None
while (is_systemd_service_running(f'hostapd@{interface}.service') or \
is_systemd_service_active(f'hostapd@{interface}.service')):
sleep(0.250) # wait 250ms
# Finally create the new interface
w = WiFiIf(**wifi)
w.update(wifi)
# Enable/Disable interface - interface is always placed in
# administrative down state in WiFiIf class
if 'disable' not in wifi:
# Wait until interface was properly added to the Kernel
ii = 0
while not (interface_exists(interface) and ii < 20):
sleep(0.250) # wait 250ms
ii += 1
# Physical interface is now configured. Proceed by starting hostapd or
# wpa_supplicant daemon. When type is monitor we can just skip this.
if wifi['type'] == 'access-point':
call(f'systemctl start hostapd@{interface}.service')
elif wifi['type'] == 'station':
call(f'systemctl start wpa_supplicant@{interface}.service')
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/system_wireless.py b/src/conf_mode/system_wireless.py
new file mode 100644
index 000000000..e0ca0ab8e
--- /dev/null
+++ b/src/conf_mode/system_wireless.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.configdep import set_dependents
+from vyos.configdep import call_dependents
+from vyos import ConfigError
+from vyos import airbag
+airbag.enable()
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['system', 'wireless']
+ interface_base = ['interfaces', 'wireless']
+
+ wireless = conf.get_config_dict(base, key_mangling=('-', '_'),
+ get_first_key=True)
+
+
+ if conf.exists(interface_base):
+ wireless['interfaces'] = conf.list_nodes(interface_base)
+ for interface in wireless['interfaces']:
+ set_dependents('wireless', conf, interface)
+
+ return wireless
+
+def verify(wireless):
+ pass
+
+def generate(wireless):
+ pass
+
+def apply(wireless):
+ if 'interfaces' in wireless:
+ call_dependents()
+ pass
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/migration-scripts/interfaces/32-to-33 b/src/migration-scripts/interfaces/32-to-33
new file mode 100755
index 000000000..caf588474
--- /dev/null
+++ b/src/migration-scripts/interfaces/32-to-33
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# T6318: WiFi country-code should be set system-wide instead of per-device
+
+from sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+if len(argv) < 2:
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['interfaces', 'wireless']
+
+config = ConfigTree(config_file)
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+installed = False
+for interface in config.list_nodes(base):
+ cc_path = base + [interface, 'country-code']
+ if config.exists(cc_path):
+ tmp = config.return_value(cc_path)
+ config.delete(cc_path)
+
+ # There can be only ONE wireless country-code per device, everything
+ # else makes no sense as a WIFI router can not operate in two
+ # different countries
+ if not installed:
+ config.set(['system', 'wireless', 'country-code'], value=tmp)
+ installed = True
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ exit(1)

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 11, 10:19 AM (23 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3224982
Default Alt Text
(78 KB)

Event Timeline