aadb7cd
#!/usr/bin/python2
aadb7cd
# -*- coding: utf-8 -*-
aadb7cd
"""
aadb7cd
@author: Tomas Hozza <thozza@redhat.com>
aadb7cd
"""
aadb7cd
aadb7cd
from gi.repository import NMClient
aadb7cd
import socket
aadb7cd
import struct
aadb7cd
import subprocess
aadb7cd
import os
aadb7cd
import os.path
aadb7cd
import syslog
aadb7cd
import sys
aadb7cd
aadb7cd
aadb7cd
# DO NOT CHANGE THE VALUE HERE, CHANGE IT IN **DNSSEC_CONF** file
aadb7cd
DEFAULT_VALIDATE_FORWARD_ZONES = True
aadb7cd
DEFAULT_ADD_WIFI_PROVIDED_ZONES = False
aadb7cd
aadb7cd
STATE_DIR = "/var/run/dnssec-trigger"
aadb7cd
DNSSEC_CONF = "/etc/dnssec.conf"
aadb7cd
aadb7cd
UNBOUND = "/usr/sbin/unbound"
aadb7cd
UNBOUND_CONTROL = "/usr/sbin/unbound-control"
aadb7cd
DNSSEC_TRIGGER = "/usr/sbin/dnssec-triggerd"
aadb7cd
DNSSEC_TRIGGER_CONTROL = "/usr/sbin/dnssec-trigger-control"
aadb7cd
PIDOF = "/usr/sbin/pidof"
aadb7cd
aadb7cd
aadb7cd
class FZonesConfig:
aadb7cd
aadb7cd
    """
aadb7cd
    Class representing dnssec-trigger script forward zones behaviour
aadb7cd
    configuration.
aadb7cd
    """
aadb7cd
aadb7cd
    def __init__(self):
aadb7cd
        self.validate_fzones = DEFAULT_VALIDATE_FORWARD_ZONES
aadb7cd
        self.add_wifi_zones = DEFAULT_ADD_WIFI_PROVIDED_ZONES
aadb7cd
aadb7cd
aadb7cd
class ActiveConnection:
aadb7cd
aadb7cd
    """
aadb7cd
    Simple class representing NM Active Connection with information relevant
aadb7cd
    for this script.
aadb7cd
    """
aadb7cd
aadb7cd
    TYPE_WIFI = "WIFI"
aadb7cd
    TYPE_VPN = "VPN"
aadb7cd
    TYPE_OTHER = "OTHER"
aadb7cd
aadb7cd
    def __init__(self):
aadb7cd
        self.type = self.TYPE_OTHER
aadb7cd
        self.is_default = False
aadb7cd
        self.nameservers = []
aadb7cd
        self.domains = []
aadb7cd
        self.uuid = ""
aadb7cd
        pass
aadb7cd
aadb7cd
    def __str__(self):
aadb7cd
        string = "UUID: " + self.get_uuid() + "\n"
aadb7cd
        string += "TYPE: " + str(self.get_type()) + "\n"
aadb7cd
        string += "DEFAULT: " + str(self.get_is_default()) + "\n"
aadb7cd
        string += "NS: " + str(self.get_nameservers()) + "\n"
aadb7cd
        string += "DOMAINS: " + str(self.get_domains())
aadb7cd
        return string
aadb7cd
aadb7cd
    def get_uuid(self):
aadb7cd
        return self.uuid
aadb7cd
aadb7cd
    def get_type(self):
aadb7cd
        return self.type
aadb7cd
aadb7cd
    def get_is_default(self):
aadb7cd
        return self.is_default
aadb7cd
aadb7cd
    def get_nameservers(self):
aadb7cd
        return self.nameservers
aadb7cd
aadb7cd
    def get_domains(self):
aadb7cd
        return self.domains
aadb7cd
aadb7cd
    def set_uuid(self, uuid=""):
aadb7cd
        self.uuid = uuid
aadb7cd
aadb7cd
    def set_type(self, conn_type=TYPE_OTHER):
aadb7cd
        if conn_type == self.TYPE_VPN:
aadb7cd
            self.type = self.TYPE_VPN
aadb7cd
        elif conn_type == self.TYPE_WIFI:
aadb7cd
            self.type = self.TYPE_WIFI
aadb7cd
        else:
aadb7cd
            self.type = self.TYPE_OTHER
aadb7cd
aadb7cd
    def set_is_default(self, is_default=True):
aadb7cd
        self.is_default = is_default
aadb7cd
aadb7cd
    def set_nameservers(self, servers=[]):
aadb7cd
        self.nameservers = servers
aadb7cd
aadb7cd
    def set_domains(self, domains=[]):
aadb7cd
        self.domains = domains
aadb7cd
aadb7cd
aadb7cd
def ip4_to_str(ip4):
aadb7cd
    """
aadb7cd
    Converts IPv4 address from integer to string.
aadb7cd
    """
aadb7cd
    return socket.inet_ntop(socket.AF_INET, struct.pack("=I", ip4))
aadb7cd
aadb7cd
aadb7cd
def ip6_to_str(ip6):
aadb7cd
    """
aadb7cd
    Converts IPv6 address from integer to string.
aadb7cd
    """
aadb7cd
    addr_struct = ip6
aadb7cd
    return socket.inet_ntop(socket.AF_INET6, addr_struct)
aadb7cd
aadb7cd
aadb7cd
def get_fzones_settings_from_conf(conf_file=""):
aadb7cd
    """
aadb7cd
    Reads the forward zones behaviour config from file.
aadb7cd
    """
aadb7cd
    config = FZonesConfig()
aadb7cd
aadb7cd
    try:
aadb7cd
        with open(conf_file, "r") as f:
aadb7cd
            lines = [l.strip()
aadb7cd
                     for l in f.readlines() if l.strip() and not l.strip().startswith("#")]
aadb7cd
            for line in lines:
aadb7cd
                option_line = line.split("=")
aadb7cd
                if option_line:
aadb7cd
                    if option_line[0].strip() == "validate_connection_provided_zones":
aadb7cd
                        if option_line[1].strip() == "yes":
aadb7cd
                            config.validate_fzones = True
aadb7cd
                        else:
aadb7cd
                            config.validate_fzones = False
aadb7cd
                    elif option_line[0].strip() == "add_wifi_provided_zones":
aadb7cd
                        if option_line[1].strip() == "yes":
aadb7cd
                            config.add_wifi_zones = True
aadb7cd
                        else:
aadb7cd
                            config.add_wifi_zones = False
aadb7cd
    except IOError:
aadb7cd
        # we don't mind if the config file does not exist
aadb7cd
        pass
aadb7cd
aadb7cd
    return config
aadb7cd
aadb7cd
aadb7cd
def get_nm_active_connections():
aadb7cd
    """
aadb7cd
    Process Active Connections from NM and return list of ActiveConnection
aadb7cd
    objects. Active Connections from NM without nameservers are ignored.
aadb7cd
    """
aadb7cd
    result = []
aadb7cd
    client = NMClient.Client()
aadb7cd
    ac = client.get_active_connections()
aadb7cd
aadb7cd
    for connection in ac:
aadb7cd
        new_connection = ActiveConnection()
aadb7cd
aadb7cd
        # get the UUID
aadb7cd
        new_connection.set_uuid(connection.get_uuid())
aadb7cd
aadb7cd
        # Find out if the ActiveConnection is VPN, WIFI or OTHER
aadb7cd
        try:
aadb7cd
            connection.get_vpn_state()
aadb7cd
        except AttributeError:
aadb7cd
            # We don't need to change anything
aadb7cd
            pass
aadb7cd
        else:
aadb7cd
            new_connection.set_type(ActiveConnection.TYPE_VPN)
aadb7cd
aadb7cd
        # if the connection is NOT VPN, then check if it's WIFI
aadb7cd
        if new_connection.get_type() != ActiveConnection.TYPE_VPN:
aadb7cd
            try:
aadb7cd
                device_type = connection.get_devices()[
aadb7cd
                    0].get_device_type().value_name
aadb7cd
            except AttributeError:
aadb7cd
                # We don't need to change anything
aadb7cd
                pass
aadb7cd
            else:
aadb7cd
                if device_type == "NM_DEVICE_TYPE_WIFI":
aadb7cd
                    new_connection.set_type(ActiveConnection.TYPE_WIFI)
aadb7cd
aadb7cd
        # Finc out if default connection for IP4 or IP6
aadb7cd
        if connection.get_default() or connection.get_default6():
aadb7cd
            new_connection.set_is_default(True)
aadb7cd
        else:
aadb7cd
            new_connection.set_is_default(False)
aadb7cd
aadb7cd
        # Get nameservers (IP4 + IP6)
aadb7cd
        ips = []
aadb7cd
        try:
aadb7cd
            ips4_int = connection.get_ip4_config().get_nameservers()
aadb7cd
        except AttributeError:
aadb7cd
            # we don't mind if there are no IP4 nameservers
aadb7cd
            pass
aadb7cd
        else:
aadb7cd
            for ip4 in ips4_int:
aadb7cd
                ips.append(ip4_to_str(ip4))
aadb7cd
        try:
aadb7cd
            num = connection.get_ip6_config().get_num_nameservers()
aadb7cd
            for i in range(0,num):
aadb7cd
                ips.append(ip6_to_str(connection.get_ip6_config().get_nameserver(i)))
aadb7cd
        except AttributeError:
aadb7cd
            # we don't mind if there are no IP6 nameservers
aadb7cd
            pass
aadb7cd
        new_connection.set_nameservers(ips)
aadb7cd
aadb7cd
        # Get domains (IP4 + IP6)
aadb7cd
        domains = []
aadb7cd
        try:
aadb7cd
            domains.extend(connection.get_ip4_config().get_domains())
aadb7cd
        except AttributeError:
aadb7cd
            # we don't mind if there are no IP6 domains
aadb7cd
            pass
aadb7cd
        try:
aadb7cd
            domains.extend(connection.get_ip6_config().get_domains())
aadb7cd
        except AttributeError:
aadb7cd
            # we don't mind if there are no IP6 domains
aadb7cd
            pass
aadb7cd
        new_connection.set_domains(domains)
aadb7cd
aadb7cd
        # If there are no nameservers in the connection, it is useless
aadb7cd
        if new_connection.get_nameservers():
aadb7cd
            result.append(new_connection)
aadb7cd
aadb7cd
    return result
aadb7cd
aadb7cd
aadb7cd
def is_running(binary=""):
aadb7cd
    """
aadb7cd
    Checks if the given binary is running.
aadb7cd
    """
aadb7cd
    if binary:
aadb7cd
        sp = subprocess.Popen(PIDOF + " " + binary,
aadb7cd
                              stdout=subprocess.PIPE,
aadb7cd
                              stderr=open(os.devnull, "wb"),
aadb7cd
                              shell=True)
aadb7cd
        sp.wait()
aadb7cd
        if sp.returncode == 0:
aadb7cd
            # pidof returns "0" if at least one program with the name runs
aadb7cd
            return True
aadb7cd
    return False
aadb7cd
aadb7cd
aadb7cd
def dnssec_trigger_set_global_ns(servers=[]):
aadb7cd
    """
aadb7cd
    Configures global nameservers into dnssec-trigger.
aadb7cd
    """
aadb7cd
    if servers:
aadb7cd
        servers_list = " ".join(servers)
aadb7cd
        ret = subprocess.call(
aadb7cd
            DNSSEC_TRIGGER_CONTROL + " submit " + servers_list,
aadb7cd
            stdout=open(os.devnull, "wb"),
aadb7cd
            stderr=subprocess.STDOUT,
aadb7cd
            shell=True)
aadb7cd
        if ret == 0:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_INFO, "Global forwarders added: " + servers_list)
aadb7cd
        else:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_ERR, "Global forwarders NOT added: " + servers_list)
aadb7cd
aadb7cd
aadb7cd
def unbound_add_forward_zone(domain="", servers=[], secure=DEFAULT_VALIDATE_FORWARD_ZONES):
aadb7cd
    """
aadb7cd
    Adds a forward zone into the unbound.
aadb7cd
    """
aadb7cd
    if domain and servers:
aadb7cd
        servers_list = " ".join(servers)
aadb7cd
        # build the command
aadb7cd
        cmd = UNBOUND_CONTROL + " forward_add"
aadb7cd
        if not secure:
aadb7cd
            cmd += " +i"
aadb7cd
        cmd += " " + domain + " " + servers_list
aadb7cd
        # Add the forward zone
aadb7cd
        ret = subprocess.call(cmd,
aadb7cd
                              stdout=open(os.devnull, "wb"),
aadb7cd
                              stderr=subprocess.STDOUT,
aadb7cd
                              shell=True)
aadb7cd
        # Flush cache
aadb7cd
        subprocess.call(UNBOUND_CONTROL + " flush_zone " + domain,
aadb7cd
                        stdout=open(os.devnull, "wb"),
aadb7cd
                        stderr=subprocess.STDOUT,
aadb7cd
                        shell=True)
aadb7cd
        subprocess.call(UNBOUND_CONTROL + " flush_requestlist",
aadb7cd
                        stdout=open(os.devnull, "wb"),
aadb7cd
                        stderr=subprocess.STDOUT,
aadb7cd
                        shell=True)
aadb7cd
aadb7cd
        if secure:
aadb7cd
            validated = "(DNSSEC validated)"
aadb7cd
        else:
aadb7cd
            validated = "(*NOT* DNSSEC validated)"
aadb7cd
aadb7cd
        if ret == 0:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_INFO, "Added " + validated + " connection provided forward zone '" + domain + "' with NS: " + servers_list)
aadb7cd
        else:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_ERR, "NOT added connection provided forward zone '" + domain + "' with NS: " + servers_list)
aadb7cd
aadb7cd
aadb7cd
def unbound_del_forward_zone(domain="", secure=DEFAULT_VALIDATE_FORWARD_ZONES):
aadb7cd
    """
aadb7cd
    Deletes a forward zone from the unbound.
aadb7cd
    """
aadb7cd
    if domain:
aadb7cd
        cmd = UNBOUND_CONTROL + " forward_remove"
aadb7cd
        if not secure:
aadb7cd
            cmd += " +i"
aadb7cd
        cmd += " " + domain
aadb7cd
        # Remove the forward zone
aadb7cd
        ret = subprocess.call(cmd,
aadb7cd
                              stdout=open(os.devnull, "wb"),
aadb7cd
                              stderr=subprocess.STDOUT,
aadb7cd
                              shell=True)
aadb7cd
        # Flush cache
aadb7cd
        subprocess.call(UNBOUND_CONTROL + " flush_zone " + domain,
aadb7cd
                        stdout=open(os.devnull, "wb"),
aadb7cd
                        stderr=subprocess.STDOUT,
aadb7cd
                        shell=True)
aadb7cd
        subprocess.call(UNBOUND_CONTROL + " flush_requestlist",
aadb7cd
                        stdout=open(os.devnull, "wb"),
aadb7cd
                        stderr=subprocess.STDOUT,
aadb7cd
                        shell=True)
aadb7cd
        if ret == 0:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_INFO, "Removed connection provided forward zone '" + domain + "'")
aadb7cd
        else:
aadb7cd
            syslog.syslog(
aadb7cd
                syslog.LOG_ERR, "NOT removed connection provided forward zone '" + domain + "'")
aadb7cd
aadb7cd
aadb7cd
def unbound_get_forward_zones():
aadb7cd
    """
aadb7cd
    Returns list of currently configured forward zones from the unbound.
aadb7cd
    """
aadb7cd
    zones = []
aadb7cd
    # get all configured forward zones
aadb7cd
    sp = subprocess.Popen(UNBOUND_CONTROL + " list_forwards",
aadb7cd
                          stdout=subprocess.PIPE,
aadb7cd
                          stderr=open(os.devnull, "wb"),
aadb7cd
                          shell=True)
aadb7cd
aadb7cd
    sp.wait()
aadb7cd
aadb7cd
    if sp.returncode == 0:
aadb7cd
        for line in sp.stdout.readlines():
aadb7cd
            zones.append(line.strip().split(" ")[0][:-1])
aadb7cd
aadb7cd
    return zones
aadb7cd
aadb7cd
##############################################################################
aadb7cd
aadb7cd
aadb7cd
def append_fzone_to_file(uuid="", zone=""):
aadb7cd
    """
aadb7cd
    Append forward zones from connection with UUID to the disk file.
aadb7cd
    """
aadb7cd
    if uuid and zone:
aadb7cd
        with open(os.path.join(STATE_DIR, uuid), "a") as f:
aadb7cd
            f.write(zone + "\n")
aadb7cd
aadb7cd
aadb7cd
def write_fzones_to_file(uuid="", zones=[]):
aadb7cd
    """
aadb7cd
    Write forward zones from connection with UUID to the disk file.
aadb7cd
    """
aadb7cd
    if uuid and zones:
aadb7cd
        with open(os.path.join(STATE_DIR, uuid), "w") as f:
aadb7cd
            for zone in zones:
aadb7cd
                f.write(zone + "\n")
aadb7cd
aadb7cd
aadb7cd
def get_fzones_from_file(uuid=""):
aadb7cd
    """
aadb7cd
    Gets all zones from a file with specified UUID name din STATE_DIR
aadb7cd
    """
aadb7cd
    zones = []
aadb7cd
    if uuid:
aadb7cd
        with open(os.path.join(STATE_DIR, uuid), "r") as f:
aadb7cd
            zones = [line.strip() for line in f.readlines()]
aadb7cd
    return zones
aadb7cd
aadb7cd
aadb7cd
def get_fzones_from_disk():
aadb7cd
    """
aadb7cd
    Gets all forward zones from the disk STATE_DIR.
aadb7cd
    Return a dict of "zone" : "connection UUID"
aadb7cd
    """
aadb7cd
    zones = {}
aadb7cd
    conn_files = os.listdir(STATE_DIR)
aadb7cd
    for uuid in conn_files:
aadb7cd
        for zone in get_fzones_from_file(uuid):
aadb7cd
            zones[zone] = uuid
aadb7cd
    return zones
aadb7cd
aadb7cd
aadb7cd
def del_all_fzones_from_file(uuid="", secure=DEFAULT_VALIDATE_FORWARD_ZONES):
aadb7cd
    """
aadb7cd
    Removes all forward zones contained in file with UUID name in STATE_DIR.
aadb7cd
    """
aadb7cd
    if uuid:
aadb7cd
        with open(os.path.join(STATE_DIR, uuid), "r") as f:
aadb7cd
            for line in f.readlines():
aadb7cd
                unbound_del_forward_zone(line.strip(), secure)
aadb7cd
aadb7cd
aadb7cd
def del_fzones_for_nonexisting_conn(ac=[], secure=DEFAULT_VALIDATE_FORWARD_ZONES):
aadb7cd
    """
aadb7cd
    Removes all forward zones contained in file (in STATE_DIR) for non-existing
aadb7cd
    active connections.
aadb7cd
    """
aadb7cd
    ac_uuid_list = [conn.get_uuid() for conn in ac]
aadb7cd
    conn_files = os.listdir(STATE_DIR)
aadb7cd
    # Remove all non-existing connections zones
aadb7cd
    for uuid in conn_files:
aadb7cd
        if uuid not in ac_uuid_list:
aadb7cd
            # remove all zones from the file
aadb7cd
            del_all_fzones_from_file(uuid, secure)
aadb7cd
            # remove the file
aadb7cd
            os.unlink(os.path.join(STATE_DIR, uuid))
aadb7cd
aadb7cd
aadb7cd
def del_fzone_from_file(uuid="", zone=""):
aadb7cd
    """
aadb7cd
    Deletes a zone from file and writes changes into it. If there are no zones
aadb7cd
    left, the file is deleted.
aadb7cd
    """
aadb7cd
    if uuid and zone:
aadb7cd
        zones = get_fzones_from_file(uuid)
aadb7cd
        zones.remove(zone)
aadb7cd
        if zones:
aadb7cd
            write_fzones_to_file(uuid, zones)
aadb7cd
        else:
aadb7cd
            os.unlink(os.path.join(STATE_DIR, uuid))
aadb7cd
aadb7cd
aadb7cd
##############################################################################
aadb7cd
aadb7cd
aadb7cd
def configure_global_forwarders(active_connections=[]):
aadb7cd
    """
aadb7cd
    Configure global forwarders using dnssec-trigger-control
aadb7cd
    """
aadb7cd
    # get only default connections
aadb7cd
    default_conns = filter(lambda x: x.get_is_default(), active_connections)
aadb7cd
    # get forwarders from default connections
aadb7cd
    default_forwarders = []
aadb7cd
    for conn in default_conns:
aadb7cd
        default_forwarders.extend(conn.get_nameservers())
aadb7cd
aadb7cd
    if default_forwarders:
aadb7cd
        dnssec_trigger_set_global_ns(default_forwarders)
aadb7cd
aadb7cd
##############################################################################
aadb7cd
aadb7cd
aadb7cd
def configure_forward_zones(active_connections=[], fzones_config=None):
aadb7cd
    """
aadb7cd
    Configures forward zones in the unbound using unbound-control.
aadb7cd
    """
aadb7cd
    # Filter out WIFI connections if desirable
aadb7cd
    if not fzones_config.add_wifi_zones:
aadb7cd
        connections = filter(
aadb7cd
            lambda x: x.get_type() != ActiveConnection.TYPE_WIFI, active_connections)
aadb7cd
    else:
aadb7cd
        connections = active_connections
aadb7cd
    # If validate forward zones
aadb7cd
    secure = fzones_config.validate_fzones
aadb7cd
aadb7cd
    # Filter active connections with domain(s)
aadb7cd
    conns_with_domains = filter(lambda x: x.get_domains(), connections)
aadb7cd
    fzones_from_ac = {}
aadb7cd
    # Construct dict of domain -> active connection
aadb7cd
    for conn in conns_with_domains:
aadb7cd
        # iterate through all domains in the active connection
aadb7cd
        for domain in conn.get_domains():
aadb7cd
            # if there is already such a domain
aadb7cd
            if domain in fzones_from_ac:
aadb7cd
                # if the "conn" is VPN and the conn for existing domain is not
aadb7cd
                if fzones_from_ac[domain].get_type() != ActiveConnection.TYPE_VPN and conn.get_type() == ActiveConnection.TYPE_VPN:
aadb7cd
                    fzones_from_ac[domain] = conn
aadb7cd
                # if none of there connections are VPNs or both are VPNs,
aadb7cd
                # prefer the default one
aadb7cd
                elif not fzones_from_ac[domain].get_is_default() and conn.get_is_default():
aadb7cd
                    fzones_from_ac[domain] = conn
aadb7cd
            else:
aadb7cd
                fzones_from_ac[domain] = conn
aadb7cd
aadb7cd
    # Remove all zones which connection UUID does not match any existing AC
aadb7cd
    del_fzones_for_nonexisting_conn(conns_with_domains, secure)
aadb7cd
aadb7cd
    # Remove all zones which connection UUID is different than the current AC
aadb7cd
    # UUID for the zone
aadb7cd
    fzones_from_disk = get_fzones_from_disk()
aadb7cd
    for zone, uuid in fzones_from_disk.iteritems():
aadb7cd
        connection = fzones_from_ac[zone]
aadb7cd
        # if the AC UUID is NOT the same as from the disk, remove the zone
aadb7cd
        if connection.get_uuid() != uuid:
aadb7cd
            unbound_del_forward_zone(zone, secure)
aadb7cd
            del_fzone_from_file(uuid, zone)
aadb7cd
aadb7cd
    # get zones from unbound and delete them from fzones_from_ac
aadb7cd
    # there may be zones manually configured in unbound.conf and we
aadb7cd
    # don't want to replace them
aadb7cd
    unbound_zones = unbound_get_forward_zones()
aadb7cd
    for zone in unbound_zones:
aadb7cd
        try:
aadb7cd
            del fzones_from_ac[zone]
aadb7cd
        except KeyError:
aadb7cd
            # we don't mind if there is no such zone
aadb7cd
            pass
aadb7cd
aadb7cd
    # Add forward zones that are not already configured
aadb7cd
    fzones_from_disk = get_fzones_from_disk()
aadb7cd
    for zone, connection in fzones_from_ac.iteritems():
aadb7cd
        if zone not in fzones_from_disk:
aadb7cd
            unbound_add_forward_zone(
aadb7cd
                zone, connection.get_nameservers(), secure)
aadb7cd
            append_fzone_to_file(connection.get_uuid(), zone)
aadb7cd
aadb7cd
aadb7cd
##############################################################################
aadb7cd
aadb7cd
aadb7cd
if __name__ == "__main__":
aadb7cd
    if not is_running(DNSSEC_TRIGGER):
aadb7cd
        syslog.syslog(syslog.LOG_ERR, "dnssec-triggerd daemon is not running!")
aadb7cd
        sys.exit(1)
aadb7cd
    if not is_running(UNBOUND):
aadb7cd
        syslog.syslog(syslog.LOG_ERR, "unbound server daemon is not running!")
aadb7cd
        sys.exit(1)
aadb7cd
aadb7cd
    fzones_config = get_fzones_settings_from_conf(DNSSEC_CONF)
aadb7cd
aadb7cd
    # Get all actove connections from NM
aadb7cd
    ac = get_nm_active_connections()
aadb7cd
    # Configure global forwarders
aadb7cd
    configure_global_forwarders(ac)
aadb7cd
    # Configure forward zones
aadb7cd
    configure_forward_zones(ac, fzones_config)