diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/firewall.py | 48 | ||||
| -rw-r--r-- | python/vyos/ifconfig/interface.py | 28 | ||||
| -rw-r--r-- | python/vyos/pki.py | 2 | ||||
| -rw-r--r-- | python/vyos/qos/base.py | 5 | ||||
| -rw-r--r-- | python/vyos/utils/convert.py | 23 | ||||
| -rw-r--r-- | python/vyos/utils/io.py | 5 | 
6 files changed, 73 insertions, 38 deletions
| diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 946050a82..d7b7b80a8 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -32,7 +32,6 @@ from vyos.utils.process import cmd  from vyos.utils.process import run  # Conntrack -  def conntrack_required(conf):      required_nodes = ['nat', 'nat66', 'load-balancing wan'] @@ -454,8 +453,28 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):                  else:                      output.append(f'set update ip{def_suffix} saddr @DA{def_suffix}_{dyn_group}') +    set_table = False      if 'set' in rule_conf: -        output.append(parse_policy_set(rule_conf['set'], def_suffix)) +        # Parse set command used in policy route: +        if 'connection_mark' in rule_conf['set']: +            conn_mark = rule_conf['set']['connection_mark'] +            output.append(f'ct mark set {conn_mark}') +        if 'dscp' in rule_conf['set']: +            dscp = rule_conf['set']['dscp'] +            output.append(f'ip{def_suffix} dscp set {dscp}') +        if 'mark' in rule_conf['set']: +            mark = rule_conf['set']['mark'] +            output.append(f'meta mark set {mark}') +        if 'table' in rule_conf['set']: +            set_table = True +            table = rule_conf['set']['table'] +            if table == 'main': +                table = '254' +            mark = 0x7FFFFFFF - int(table) +            output.append(f'meta mark set {mark}') +        if 'tcp_mss' in rule_conf['set']: +            mss = rule_conf['set']['tcp_mss'] +            output.append(f'tcp option maxseg size set {mss}')      if 'action' in rule_conf:          # Change action=return to action=action @@ -489,7 +508,8 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):                  output.append(f'wscale {synproxy_ws} timestamp sack-perm')      else: -        output.append('return') +        if set_table: +            output.append('return')      output.append(f'comment "{family}-{hook}-{fw_name}-{rule_id}"')      return " ".join(output) @@ -521,28 +541,6 @@ def parse_time(time):          out.append(f'day {{{",".join(out_days)}}}')      return " ".join(out) -def parse_policy_set(set_conf, def_suffix): -    out = [] -    if 'connection_mark' in set_conf: -        conn_mark = set_conf['connection_mark'] -        out.append(f'ct mark set {conn_mark}') -    if 'dscp' in set_conf: -        dscp = set_conf['dscp'] -        out.append(f'ip{def_suffix} dscp set {dscp}') -    if 'mark' in set_conf: -        mark = set_conf['mark'] -        out.append(f'meta mark set {mark}') -    if 'table' in set_conf: -        table = set_conf['table'] -        if table == 'main': -            table = '254' -        mark = 0x7FFFFFFF - int(table) -        out.append(f'meta mark set {mark}') -    if 'tcp_mss' in set_conf: -        mss = set_conf['tcp_mss'] -        out.append(f'tcp option maxseg size set {mss}') -    return " ".join(out) -  # GeoIP  nftables_geoip_conf = '/run/nftables-geoip.conf' diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 1b86982c4..f0897bc21 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1,4 +1,4 @@ -# Copyright 2019-2023 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2024 VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public @@ -193,6 +193,9 @@ class Interface(Control):              'validate': assert_positive,              'location': '/proc/sys/net/ipv6/conf/{ifname}/dad_transmits',          }, +        'ipv6_cache_tmo': { +            'location': '/proc/sys/net/ipv6/neigh/{ifname}/base_reachable_time_ms', +        },          'path_cost': {              # XXX: we should set a maximum              'validate': assert_positive, @@ -261,6 +264,9 @@ class Interface(Control):          'ipv6_dad_transmits': {              'location': '/proc/sys/net/ipv6/conf/{ifname}/dad_transmits',          }, +        'ipv6_cache_tmo': { +            'location': '/proc/sys/net/ipv6/neigh/{ifname}/base_reachable_time_ms', +        },          'proxy_arp': {              'location': '/proc/sys/net/ipv4/conf/{ifname}/proxy_arp',          }, @@ -613,6 +619,21 @@ class Interface(Control):              return None          return self.set_interface('arp_cache_tmo', tmo) +    def set_ipv6_cache_tmo(self, tmo): +        """ +        Set IPv6 cache timeout value in seconds. Internal Kernel representation +        is in milliseconds. + +        Example: +        >>> from vyos.ifconfig import Interface +        >>> Interface('eth0').set_ipv6_cache_tmo(40) +        """ +        tmo = str(int(tmo) * 1000) +        tmp = self.get_interface('ipv6_cache_tmo') +        if tmp == tmo: +            return None +        return self.set_interface('ipv6_cache_tmo', tmo) +      def _cleanup_mss_rules(self, table, ifname):          commands = []          results = self._cmd(f'nft -a list chain {table} VYOS_TCP_MSS').split("\n") @@ -1698,6 +1719,11 @@ class Interface(Control):              for addr in tmp:                  self.add_ipv6_eui64_address(addr) +        # Configure IPv6 base time in milliseconds - has default value +        tmp = dict_search('ipv6.base_reachable_time', config) +        value = tmp if (tmp != None) else '30' +        self.set_ipv6_cache_tmo(value) +          # re-add ourselves to any bridge we might have fallen out of          if 'is_bridge_member' in config:              tmp = config.get('is_bridge_member') diff --git a/python/vyos/pki.py b/python/vyos/pki.py index 3c577db4d..27fe793a8 100644 --- a/python/vyos/pki.py +++ b/python/vyos/pki.py @@ -146,7 +146,7 @@ def create_certificate_request(subject, private_key, subject_alt_names=[]):              if isinstance(obj, ipaddress.IPv4Address) or isinstance(obj, ipaddress.IPv6Address):                  alt_names.append(x509.IPAddress(obj))              elif isinstance(obj, str): -                alt_names.append(x509.DNSName(obj)) +                alt_names.append(x509.RFC822Name(obj) if '@' in obj else x509.DNSName(obj))          if alt_names:              builder = builder.add_extension(x509.SubjectAlternativeName(alt_names), critical=False) diff --git a/python/vyos/qos/base.py b/python/vyos/qos/base.py index f9366c6b1..4173a1a43 100644 --- a/python/vyos/qos/base.py +++ b/python/vyos/qos/base.py @@ -246,6 +246,7 @@ class QoSBase:                  filter_cmd_base += ' protocol all'                  if 'match' in cls_config: +                    is_filtered = False                      for index, (match, match_config) in enumerate(cls_config['match'].items(), start=1):                          filter_cmd = filter_cmd_base                          if self.qostype == 'shaper' and 'prio ' not in filter_cmd: @@ -330,11 +331,13 @@ class QoSBase:                                  cls = int(cls)                                  filter_cmd += f' flowid {self._parent:x}:{cls:x}'                                  self._cmd(filter_cmd) +                                is_filtered = True                      vlan_expression = "match.*.vif"                      match_vlan = jmespath.search(vlan_expression, cls_config) -                    if any(tmp in ['exceed', 'bandwidth', 'burst'] for tmp in cls_config): +                    if any(tmp in ['exceed', 'bandwidth', 'burst'] for tmp in cls_config) \ +                        and is_filtered:                          # For "vif" "basic match" is used instead of "action police" T5961                          if not match_vlan:                              filter_cmd += f' action police' diff --git a/python/vyos/utils/convert.py b/python/vyos/utils/convert.py index c02f0071e..41e65081f 100644 --- a/python/vyos/utils/convert.py +++ b/python/vyos/utils/convert.py @@ -1,4 +1,4 @@ -# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2023-2024 VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public @@ -19,38 +19,43 @@ def seconds_to_human(s, separator=""):      """      s = int(s) +    year = 60 * 60 * 24 * 365.25      week = 60 * 60 * 24 * 7      day = 60 * 60 * 24      hour = 60 * 60 -    remainder = 0 -    result = "" +    result = [] + +    years = s // year +    if years > 0: +        result.append(f'{int(years)}y') +        s = int(s % year)      weeks = s // week      if weeks > 0: -        result = "{0}w".format(weeks) +        result.append(f'{weeks}w')          s = s % week      days = s // day      if days > 0: -        result = "{0}{1}{2}d".format(result, separator, days) +        result.append(f'{days}d')          s = s % day      hours = s // hour      if hours > 0: -        result = "{0}{1}{2}h".format(result, separator, hours) +        result.append(f'{hours}h')          s = s % hour      minutes = s // 60      if minutes > 0: -        result = "{0}{1}{2}m".format(result, separator, minutes) +        result.append(f'{minutes}m')          s = s % 60      seconds = s      if seconds > 0: -        result = "{0}{1}{2}s".format(result, separator, seconds) +        result.append(f'{seconds}s') -    return result +    return separator.join(result)  def bytes_to_human(bytes, initial_exponent=0, precision=2,                     int_below_exponent=0): diff --git a/python/vyos/utils/io.py b/python/vyos/utils/io.py index 7e6045291..a8c430f28 100644 --- a/python/vyos/utils/io.py +++ b/python/vyos/utils/io.py @@ -27,7 +27,7 @@ def print_error(str='', end='\n'):      sys.stderr.flush()  def ask_input(question, default='', numeric_only=False, valid_responses=[], -              no_echo=False): +              no_echo=False, non_empty=False):      from getpass import getpass      question_out = question      if default: @@ -48,6 +48,9 @@ def ask_input(question, default='', numeric_only=False, valid_responses=[],          if valid_responses and response not in valid_responses:              print("Invalid value, try again.")              continue +        if non_empty and not response: +            print("Non-empty value required; try again.") +            continue          break      return response | 
