summaryrefslogtreecommitdiff
path: root/src/conf_mode/dns_dynamic.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode/dns_dynamic.py')
-rwxr-xr-xsrc/conf_mode/dns_dynamic.py43
1 files changed, 30 insertions, 13 deletions
diff --git a/src/conf_mode/dns_dynamic.py b/src/conf_mode/dns_dynamic.py
index ab80defe8..874c4b689 100755
--- a/src/conf_mode/dns_dynamic.py
+++ b/src/conf_mode/dns_dynamic.py
@@ -19,6 +19,7 @@ import os
from sys import exit
from vyos.config import Config
+from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.utils.process import call
from vyos import ConfigError
@@ -29,25 +30,32 @@ config_file = r'/run/ddclient/ddclient.conf'
systemd_override = r'/run/systemd/system/ddclient.service.d/override.conf'
# Protocols that require zone
-zone_allowed = ['cloudflare', 'godaddy', 'hetzner', 'gandi', 'nfsn']
+zone_necessary = ['cloudflare', 'godaddy', 'hetzner', 'gandi', 'nfsn']
# Protocols that do not require username
username_unnecessary = ['1984', 'cloudflare', 'cloudns', 'duckdns', 'freemyip', 'hetzner', 'keysystems', 'njalla']
+# Protocols that support TTL
+ttl_supported = ['cloudflare', 'gandi', 'hetzner', 'dnsexit', 'godaddy', 'nfsn']
+
# Protocols that support both IPv4 and IPv6
dualstack_supported = ['cloudflare', 'dyndns2', 'freedns', 'njalla']
+# dyndns2 protocol in ddclient honors dual stack for selective servers
+# because of the way it is implemented in ddclient
+dyndns_dualstack_servers = ['members.dyndns.org', 'dynv6.com']
+
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
- base_level = ['service', 'dns', 'dynamic']
- if not conf.exists(base_level):
+ base = ['service', 'dns', 'dynamic']
+ if not conf.exists(base):
return None
- dyndns = conf.get_config_dict(base_level, key_mangling=('-', '_'),
+ dyndns = conf.get_config_dict(base, key_mangling=('-', '_'),
no_tag_node_value_mangle=True,
get_first_key=True,
with_recursive_defaults=True)
@@ -61,6 +69,10 @@ def verify(dyndns):
return None
for address in dyndns['address']:
+ # If dyndns address is an interface, ensure it exists
+ if address != 'web':
+ verify_interface_exists(address)
+
# RFC2136 - configuration validation
if 'rfc2136' in dyndns['address'][address]:
for config in dyndns['address'][address]['rfc2136'].values():
@@ -78,25 +90,30 @@ def verify(dyndns):
if field not in config:
raise ConfigError(f'"{field.replace("_", "-")}" {error_msg}')
- if config['protocol'] in zone_allowed and 'zone' not in config:
- raise ConfigError(f'"zone" {error_msg}')
+ if config['protocol'] in zone_necessary and 'zone' not in config:
+ raise ConfigError(f'"zone" {error_msg}')
- if config['protocol'] not in zone_allowed and 'zone' in config:
- raise ConfigError(f'"{config["protocol"]}" does not support "zone"')
+ if config['protocol'] not in zone_necessary and 'zone' in config:
+ raise ConfigError(f'"{config["protocol"]}" does not support "zone"')
- if config['protocol'] not in username_unnecessary:
- if 'username' not in config:
- raise ConfigError(f'"username" {error_msg}')
+ if config['protocol'] not in username_unnecessary and 'username' not in config:
+ raise ConfigError(f'"username" {error_msg}')
+
+ if config['protocol'] not in ttl_supported and 'ttl' in config:
+ raise ConfigError(f'"{config["protocol"]}" does not support "ttl"')
if config['ip_version'] == 'both':
if config['protocol'] not in dualstack_supported:
raise ConfigError(f'"{config["protocol"]}" does not support '
f'both IPv4 and IPv6 at the same time')
# dyndns2 protocol in ddclient honors dual stack only for dyn.com (dyndns.org)
- if config['protocol'] == 'dyndns2' and 'server' in config and config['server'] != 'members.dyndns.org':
+ if config['protocol'] == 'dyndns2' and 'server' in config and config['server'] not in dyndns_dualstack_servers:
raise ConfigError(f'"{config["protocol"]}" does not support '
f'both IPv4 and IPv6 at the same time for "{config["server"]}"')
+ if {'wait_time', 'expiry_time'} <= config.keys() and int(config['expiry_time']) < int(config['wait_time']):
+ raise ConfigError(f'"expiry-time" must be greater than "wait-time"')
+
return None
def generate(dyndns):
@@ -104,7 +121,7 @@ def generate(dyndns):
if not dyndns or 'address' not in dyndns:
return None
- render(config_file, 'dns-dynamic/ddclient.conf.j2', dyndns)
+ render(config_file, 'dns-dynamic/ddclient.conf.j2', dyndns, permission=0o600)
render(systemd_override, 'dns-dynamic/override.conf.j2', dyndns)
return None