Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wireless: T6318: move country-code to a system wide configuration #3656

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions data/config-mode-dependencies/vyos-1x.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,8 @@
"wireguard": ["interfaces_wireguard"],
"wireless": ["interfaces_wireless"],
"wwan": ["interfaces_wwan"]
},
"system_wireless": {
"wireless": ["interfaces_wireless"]
}
}
1 change: 1 addition & 0 deletions data/configd-include.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"system_task-scheduler.py",
"system_timezone.py",
"system_update-check.py",
"system_wireless.py",
"vpn_ipsec.py",
"vpn_l2tp.py",
"vpn_openconnect.py",
Expand Down
Original file line number Diff line number Diff line change
@@ -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 -->
20 changes: 0 additions & 20 deletions interface-definitions/interfaces_wireless.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -451,26 +451,6 @@
</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>
Expand Down
36 changes: 36 additions & 0 deletions interface-definitions/system_wireless.xml.in
Original file line number Diff line number Diff line change
@@ -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>
25 changes: 25 additions & 0 deletions smoketest/config-tests/wireless-basic
Original file line number Diff line number Diff line change
@@ -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'
66 changes: 66 additions & 0 deletions smoketest/configs/wireless-basic
Original file line number Diff line number Diff line change
@@ -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
50 changes: 30 additions & 20 deletions smoketest/scripts/cli/test_interfaces_wireless.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,31 @@ def get_config_value(interface, key):
tmp = re.findall(f'{key}=+(.*)', tmp)
return tmp[0]

wifi_cc_path = ['system', 'wireless', 'country-code']

class WirelessInterfaceTest(BasicInterfaceTest.TestCase):
@classmethod
def setUpClass(cls):
cls._base_path = ['interfaces', 'wireless']
cls._options = {
'wlan0': ['physical-device phy0', 'ssid VyOS-WIFI-0',
'type station', 'address 192.0.2.1/30'],
'wlan1': ['physical-device phy0', 'ssid VyOS-WIFI-1', 'country-code se',
'type access-point', 'address 192.0.2.5/30', 'channel 0'],
'wlan10': ['physical-device phy1', 'ssid VyOS-WIFI-2',
'type station', 'address 192.0.2.9/30'],
'wlan11': ['physical-device phy1', 'ssid VyOS-WIFI-3', 'country-code se',
'type access-point', 'address 192.0.2.13/30', 'channel 0'],
'wlan0': ['physical-device phy0',
'ssid VyOS-WIFI-0',
'type station',
'address 192.0.2.1/30'],
'wlan1': ['physical-device phy0',
'ssid VyOS-WIFI-1',
'type access-point',
'address 192.0.2.5/30',
'channel 0'],
'wlan10': ['physical-device phy1',
'ssid VyOS-WIFI-2',
'type station',
'address 192.0.2.9/30'],
'wlan11': ['physical-device phy1',
'ssid VyOS-WIFI-3',
'type access-point',
'address 192.0.2.13/30',
'channel 0'],
}
cls._interfaces = list(cls._options)
# call base-classes classmethod
Expand All @@ -54,6 +66,8 @@ def setUpClass(cls):
cls._test_ipv6 = False
cls._test_vlan = False

cls.cli_set(cls, wifi_cc_path + ['es'])

def test_wireless_add_single_ip_address(self):
# derived method to check if member interfaces are enslaved properly
super().test_add_single_ip_address()
Expand All @@ -74,7 +88,6 @@ def test_wireless_hostapd_config(self):
ssid = 'ssid'

self.cli_set(self._base_path + [interface, 'ssid', ssid])
self.cli_set(self._base_path + [interface, 'country-code', 'se'])
self.cli_set(self._base_path + [interface, 'type', 'access-point'])

# auto-powersave is special
Expand Down Expand Up @@ -150,7 +163,7 @@ def test_wireless_hostapd_wpa_config(self):
# Only set the hostapd (access-point) options
interface = 'wlan0'
phy = 'phy0'
ssid = 'ssid'
ssid = 'VyOS-SMOKETEST'
channel = '1'
wpa_key = 'VyOSVyOSVyOS'
mode = 'n'
Expand All @@ -160,21 +173,20 @@ def test_wireless_hostapd_wpa_config(self):
self.cli_set(self._base_path + [interface, 'type', 'access-point'])
self.cli_set(self._base_path + [interface, 'mode', mode])

# Country-Code must be set
self.cli_delete(wifi_cc_path)
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(wifi_cc_path + [country])

# SSID must be set
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(self._base_path + [interface, 'ssid', ssid])

# Channel must be set
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(self._base_path + [interface, 'channel', channel])

# Country-Code must be set
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(self._base_path + [interface, 'country-code', country])

self.cli_set(self._base_path + [interface, 'security', 'wpa', 'mode', 'wpa2'])
self.cli_set(self._base_path + [interface, 'security', 'wpa', 'passphrase', wpa_key])

Expand Down Expand Up @@ -222,7 +234,6 @@ def test_wireless_access_point_bridge(self):
self.cli_set(bridge_path + ['member', 'interface', interface])

self.cli_set(self._base_path + [interface, 'ssid', ssid])
self.cli_set(self._base_path + [interface, 'country-code', 'se'])
self.cli_set(self._base_path + [interface, 'type', 'access-point'])

self.cli_commit()
Expand Down Expand Up @@ -260,7 +271,6 @@ def test_wireless_security_station_address(self):
deny_mac = ['00:00:00:00:de:01', '00:00:00:00:de:02', '00:00:00:00:de:03', '00:00:00:00:de:04']

self.cli_set(self._base_path + [interface, 'ssid', ssid])
self.cli_set(self._base_path + [interface, 'country-code', 'se'])
self.cli_set(self._base_path + [interface, 'type', 'access-point'])
self.cli_set(self._base_path + [interface, 'security', 'station-address', 'mode', 'accept'])

Expand Down Expand Up @@ -295,4 +305,4 @@ def test_wireless_security_station_address(self):

if __name__ == '__main__':
check_kmod('mac80211_hwsim')
unittest.main(verbosity=2)
unittest.main(verbosity=2, failfast=True)
11 changes: 9 additions & 2 deletions src/conf_mode/interfaces_wireless.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
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 -
Expand Down Expand Up @@ -78,7 +80,11 @@ def get_config(config=None):
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
Expand Down Expand Up @@ -131,7 +137,8 @@ def verify(wifi):

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!')
Expand Down
64 changes: 64 additions & 0 deletions src/conf_mode/system_wireless.py
Original file line number Diff line number Diff line change
@@ -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)
Loading
Loading