diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/interfaces_wireless.py | 75 | ||||
| -rwxr-xr-x | src/conf_mode/vpn_ipsec.py | 16 | ||||
| -rwxr-xr-x | src/conf_mode/vrf.py | 6 | 
3 files changed, 66 insertions, 31 deletions
| diff --git a/src/conf_mode/interfaces_wireless.py b/src/conf_mode/interfaces_wireless.py index 5fd7ab6e9..f35a250cb 100755 --- a/src/conf_mode/interfaces_wireless.py +++ b/src/conf_mode/interfaces_wireless.py @@ -19,6 +19,7 @@ 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 @@ -34,6 +35,9 @@ 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() @@ -93,6 +97,11 @@ def get_config(config=None):          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') @@ -120,7 +129,7 @@ def get_config(config=None):      tmp = find_other_stations(conf, base, wifi['ifname'])      if tmp: wifi['station_interfaces'] = tmp -    # used in hostapt.conf.j2 +    # 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) @@ -232,11 +241,6 @@ def verify(wifi):  def generate(wifi):      interface = wifi['ifname'] -    # always stop hostapd service first before reconfiguring it -    call(f'systemctl stop hostapd@{interface}.service') -    # always stop wpa_supplicant service first before reconfiguring it -    call(f'systemctl stop wpa_supplicant@{interface}.service') -      # Delete config files if interface is removed      if 'deleted' in wifi:          if os.path.isfile(hostapd_conf.format(**wifi)): @@ -272,11 +276,6 @@ def generate(wifi):              mac.dialect = mac_unix_expanded              wifi['mac'] = str(mac) -    # 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'] -      # 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) @@ -290,23 +289,45 @@ def generate(wifi):  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(interface).remove() -    else: -        # 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: -            # 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') +        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 diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index dc78c755e..cf82b767f 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -24,6 +24,7 @@ from time import sleep  from vyos.base import Warning  from vyos.config import Config +from vyos.config import config_dict_merge  from vyos.configdep import set_dependents  from vyos.configdep import call_dependents  from vyos.configdict import leaf_node_changed @@ -86,9 +87,22 @@ def get_config(config=None):      ipsec = conf.get_config_dict(base, key_mangling=('-', '_'),                                   no_tag_node_value_mangle=True,                                   get_first_key=True, -                                 with_recursive_defaults=True,                                   with_pki=True) +    # We have to cleanup the default dict, as default values could +    # enable features which are not explicitly enabled on the +    # CLI. E.g. dead-peer-detection defaults should not be injected +    # unless the feature is explicitly opted in to by setting the +    # top-level node +    default_values = conf.get_config_defaults(**ipsec.kwargs, recursive=True) + +    if 'ike_group' in ipsec: +        for name, ike in ipsec['ike_group'].items(): +            if 'dead_peer_detection' not in ike: +                del default_values['ike_group'][name]['dead_peer_detection'] + +    ipsec = config_dict_merge(default_values, ipsec) +      ipsec['dhcp_interfaces'] = set()      ipsec['dhcp_no_address'] = {}      ipsec['install_routes'] = 'no' if conf.exists(base + ["options", "disable-route-autoinstall"]) else default_install_routes diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 8d8c234c0..184725573 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -26,7 +26,7 @@ from vyos.ifconfig import Interface  from vyos.template import render  from vyos.template import render_to_string  from vyos.utils.dict import dict_search -from vyos.utils.network import get_interface_config +from vyos.utils.network import get_vrf_tableid  from vyos.utils.network import get_vrf_members  from vyos.utils.network import interface_exists  from vyos.utils.process import call @@ -160,8 +160,8 @@ def verify(vrf):              # routing table id can't be changed - OS restriction              if interface_exists(name): -                tmp = str(dict_search('linkinfo.info_data.table', get_interface_config(name))) -                if tmp and tmp != vrf_config['table']: +                tmp = get_vrf_tableid(name) +                if tmp and tmp != int(vrf_config['table']):                      raise ConfigError(f'VRF "{name}" table id modification not possible!')              # VRF routing table ID must be unique on the system | 
