diff options
| -rw-r--r-- | data/templates/dns-forwarding/recursor.forward-zones.conf.j2 | 3 | ||||
| -rw-r--r-- | interface-definitions/dns-forwarding.xml.in | 19 | ||||
| -rw-r--r-- | interface-definitions/include/name-server-ipv4-ipv6-port.xml.i | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_service_dns_forwarding.py | 13 | ||||
| -rwxr-xr-x | src/conf_mode/dns_forwarding.py | 25 | ||||
| -rwxr-xr-x | src/migration-scripts/dns-forwarding/3-to-4 | 49 | ||||
| -rwxr-xr-x | src/services/vyos-hostsd | 2 | 
7 files changed, 83 insertions, 30 deletions
diff --git a/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 b/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 index de3269e47..593a98c24 100644 --- a/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 +++ b/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 @@ -23,7 +23,6 @@  {% if forward_zones is vyos_defined %}  # zones added via 'service dns forwarding domain'  {%     for zone, zonedata in forward_zones.items() %} -{{ "+" if zonedata.recursion_desired is vyos_defined }}{{ zone | replace('_', '-') }}={{ zonedata.server | join(', ') }} +{{ "+" if zonedata.recursion_desired is vyos_defined }}{{ zone | replace('_', '-') }}={{ zonedata.name_server | join(', ') }}  {%     endfor %}  {% endif %} - diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index b23eaa351..14b38b24d 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -85,24 +85,7 @@                    <help>Domain to forward to a custom DNS server</help>                  </properties>                  <children> -                  <leafNode name="server"> -                    <properties> -                      <help>Domain Name Server (DNS) to forward queries to</help> -                      <valueHelp> -                        <format>ipv4</format> -                        <description>Domain Name Server (DNS) IPv4 address</description> -                      </valueHelp> -                      <valueHelp> -                        <format>ipv6</format> -                        <description>Domain Name Server (DNS) IPv6 address</description> -                      </valueHelp> -                      <multi/> -                      <constraint> -                        <validator name="ipv4-address"/> -                        <validator name="ipv6-address"/> -                      </constraint> -                    </properties> -                  </leafNode> +                  #include <include/name-server-ipv4-ipv6-port.xml.i>                    <leafNode name="addnta">                      <properties>                        <help>Add NTA (negative trust anchor) for this domain (must be set if the domain does not support DNSSEC)</help> diff --git a/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i b/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i index cf86e66a2..fb0a4f4ae 100644 --- a/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i +++ b/interface-definitions/include/name-server-ipv4-ipv6-port.xml.i @@ -1,7 +1,7 @@  <!-- include start from name-server-ipv4-ipv6-port.xml.i -->  <tagNode name="name-server">    <properties> -    <help>Domain Name Servers (DNS) addresses</help> +    <help>Domain Name Servers (DNS) addresses to forward queries to</help>      <valueHelp>        <format>ipv4</format>        <description>Domain Name Server (DNS) IPv4 address</description> diff --git a/smoketest/scripts/cli/test_service_dns_forwarding.py b/smoketest/scripts/cli/test_service_dns_forwarding.py index 04dced292..88492e348 100755 --- a/smoketest/scripts/cli/test_service_dns_forwarding.py +++ b/smoketest/scripts/cli/test_service_dns_forwarding.py @@ -169,10 +169,13 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):              self.cli_set(base_path + ['listen-address', address])          domains = ['vyos.io', 'vyos.net', 'vyos.com'] -        nameservers = ['192.0.2.1', '192.0.2.2'] +        nameservers = {'192.0.2.1': {}, '192.0.2.2': {'port': '53'}, '2001:db8::1': {'port': '853'}}          for domain in domains: -            for nameserver in nameservers: -                self.cli_set(base_path + ['domain', domain, 'server', nameserver]) +            for h,p in nameservers.items(): +                if 'port' in p: +                    self.cli_set(base_path + ['domain', domain, 'name-server', h, 'port', p['port']]) +                else: +                    self.cli_set(base_path + ['domain', domain, 'name-server', h])              # Test 'recursion-desired' flag for only one domain              if domain == domains[0]: @@ -192,7 +195,9 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase):              if domain == domains[0]: key =f'\+{domain}'              else: key =f'{domain}'              tmp = get_config_value(key, file=FORWARD_FILE) -            self.assertEqual(tmp, ', '.join(nameservers)) +            canonical_entries = [(lambda h, p: f"{bracketize_ipv6(h)}:{p['port'] if 'port' in p else 53}")(h, p) +                        for (h, p) in nameservers.items()] +            self.assertEqual(tmp, ', '.join(canonical_entries))              # Test 'negative trust anchor' flag for the second domain only              if domain == domains[1]: diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index 4d6b85d92..36c1098fe 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -59,6 +59,7 @@ def get_config(config=None):      # T2665 due to how defaults under tag nodes work, we must clear these out before we merge      del default_values['authoritative_domain']      del default_values['name_server'] +    del default_values['domain']['name_server']      dns = dict_merge(default_values, dns)      # T2665: we cleared default values for tag node 'name_server' above. @@ -68,6 +69,15 @@ def get_config(config=None):          for server in dns['name_server']:              dns['name_server'][server] = dict_merge(default_values, dns['name_server'][server]) +    # T2665: we cleared default values for tag node 'domain' above. +    # We now need to add them back back in a granular way. +    if 'domain' in dns: +        default_values = defaults(base + ['domain', 'name-server']) +        for domain in dns['domain'].keys(): +            for server in dns['domain'][domain]['name_server']: +                dns['domain'][domain]['name_server'][server] = dict_merge( +                    default_values, dns['domain'][domain]['name_server'][server]) +      # some additions to the default dictionary      if 'system' in dns:          base_nameservers = ['system', 'name-server'] @@ -271,7 +281,7 @@ def verify(dns):      # as a domain will contains dot's which is out dictionary delimiter.      if 'domain' in dns:          for domain in dns['domain']: -            if 'server' not in dns['domain'][domain]: +            if 'name_server' not in dns['domain'][domain]:                  raise ConfigError(f'No server configured for domain {domain}!')      if 'dns64_prefix' in dns: @@ -337,9 +347,9 @@ def apply(dns):          # sources          hc.delete_name_servers([hostsd_tag])          if 'name_server' in dns: -            # 'name_server' is a dict of the form +            # 'name_server' is of the form              # {'192.0.2.1': {'port': 53}, '2001:db8::1': {'port': 853}, ...} -            # canonicalize them as ['192.0.2.1:53', '[2001:db8::1]:853', ...] with IPv6 hosts bracketized +            # canonicalize them as ['192.0.2.1:53', '[2001:db8::1]:853', ...]              nslist = [(lambda h, p: f"{bracketize_ipv6(h)}:{p['port']}")(h, p)                        for (h, p) in dns['name_server'].items()]              hc.add_name_servers({hostsd_tag: nslist}) @@ -371,7 +381,14 @@ def apply(dns):          # the list and keys() are required as get returns a dict, not list          hc.delete_forward_zones(list(hc.get_forward_zones().keys()))          if 'domain' in dns: -            hc.add_forward_zones(dns['domain']) +            zones = dns['domain'] +            for domain in zones.keys(): +                # 'name_server' is of the form +                # {'192.0.2.1': {'port': 53}, '2001:db8::1': {'port': 853}, ...} +                # canonicalize them as ['192.0.2.1:53', '[2001:db8::1]:853', ...] +                zones[domain]['name_server'] = [(lambda h, p: f"{bracketize_ipv6(h)}:{p['port']}")(h, p) +                                                for (h, p) in zones[domain]['name_server'].items()] +            hc.add_forward_zones(zones)          # hostsd generates NTAs for the authoritative zones          # the list and keys() are required as get returns a dict, not list diff --git a/src/migration-scripts/dns-forwarding/3-to-4 b/src/migration-scripts/dns-forwarding/3-to-4 new file mode 100755 index 000000000..55165c2c5 --- /dev/null +++ b/src/migration-scripts/dns-forwarding/3-to-4 @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2023 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/>. + +# T5115: migrate "service dns forwarding domain example.com server" to +#                "service dns forwarding domain example.com name-server" + +import sys +from vyos.configtree import ConfigTree + +if (len(sys.argv) < 1): +    print("Must specify file name!") +    sys.exit(1) + +file_name = sys.argv[1] + +with open(file_name, 'r') as f: +    config_file = f.read() + +config = ConfigTree(config_file) + +base = ['service', 'dns', 'forwarding', 'domain'] +if not config.exists(base): +    # Nothing to do +    sys.exit(0) + +for domain in config.list_nodes(base): +    if config.exists(base + [domain, 'server']): +        config.copy(base + [domain, 'server'], base + [domain, 'name-server']) +        config.delete(base + [domain, 'server']) + +try: +    with open(file_name, 'w') as f: +        f.write(config.to_string()) +except OSError as e: +    print("Failed to save the modified config: {}".format(e)) +    sys.exit(1) diff --git a/src/services/vyos-hostsd b/src/services/vyos-hostsd index a380f2e66..894f9e24d 100755 --- a/src/services/vyos-hostsd +++ b/src/services/vyos-hostsd @@ -329,7 +329,7 @@ tag_regex_schema = op_type_schema.extend({  forward_zone_add_schema = op_type_schema.extend({      'data': {          str: { -            'server': [str], +            'name_server': [str],              'addnta': Any({}, None),              'recursion_desired': Any({}, None),              }  | 
