Skip to content

Commit

Permalink
feat(ns8): add DNS server running check and disabled dns toggle (#16)
Browse files Browse the repository at this point in the history
Co-authored-by: Davide Principi <[email protected]>
  • Loading branch information
stephdl and DavidePrincipi authored Aug 2, 2024
1 parent 36c54b8 commit 3c4d6dc
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 3 deletions.
11 changes: 11 additions & 0 deletions imageroot/actions/configure-module/10validate
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,14 @@ if request["dhcp-server"]["enabled"]:
agent.set_status('validation-failed')
json.dump([{'field':'dhcp-server.start', 'parameter':'dhcp-server.start','value': request['dhcp-server']['start'], 'error':'must_be_less_than_end'}], fp=sys.stdout)
sys.exit(2)

if request["dns-server"]["enabled"]:
is_dns_bound = network.are_ports_53_bound()
# read config.json and determine if dns is used for this instance
config = json.load(open("config.json"))
is_dns_enabled = config["dns-server"]["enabled"]
# check if dns is already bound to port 53 and stop the action
if is_dns_bound and not is_dns_enabled:
agent.set_status('validation-failed')
json.dump([{'field':'dnsEnableField', 'parameter':'dnsEnableField', 'value': request['dns-server']['enabled'], 'error':'dns_port_already_bind'}], fp=sys.stdout)
sys.exit(3)
6 changes: 6 additions & 0 deletions imageroot/actions/get-configuration/10get
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ if config["interface"] != "" and config["dhcp-server"]["start"] == "" and config
config["dhcp-server"]["start"] = str(interface["start"])
config["dhcp-server"]["end"] = str(interface["end"])

# we test if tcp/53 or udp/53 is bound to the interface
config["is_dns_bound"] = network.are_ports_53_bound()
# check if dnsmasq is enabled in the configuration, needed to determine in the UI if the DNS server was enabled and used by dnsmasq.
# the dnsmasq service is always running, we cannot state if it is enabled/active or not.
config['is_dns_enabled'] = config["dns-server"]["enabled"]

json.dump(config, sys.stdout)
12 changes: 11 additions & 1 deletion imageroot/actions/get-configuration/validate-output.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,21 @@
"primary-server",
"secondary-server"
]
},
"is_dns_enabled": {
"description": "True if dnsmasq is configured",
"type": "boolean"
},
"is_dns_bound": {
"description": "True if DNS servers are bound to the interface",
"type": "boolean"
}
},
"required": [
"interface",
"dhcp-server",
"dns-server"
"dns-server",
"is_dns_enabled",
"is_dns_bound"
]
}
19 changes: 19 additions & 0 deletions imageroot/pypkg/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import ipaddress
import json
import subprocess
import socket


def __filter_interface(interface):
Expand Down Expand Up @@ -59,3 +60,21 @@ def list_interfaces():
"""
subprocess_result = subprocess.run(["ip", "-4", "-j", "addr"], check=True, capture_output=True)
return [__format_interface(interface) for interface in json.loads(subprocess_result.stdout) if __filter_interface(interface)]

def __is_port_bound(port, protocol, ip='127.0.0.1'):
"""
Check if a port is already bound for a given protocol (TCP/UDP) on a specific IP address.
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM if protocol == 'tcp' else socket.SOCK_DGRAM)
try:
s.bind((ip, port))
s.close()
return False
except OSError:
return True

def are_ports_53_bound(ip='127.0.0.1'):
"""
Check if both TCP and UDP ports 53 are bound on a specific IP address.
"""
return __is_port_bound(53, 'tcp', ip) or __is_port_bound(53, 'udp', ip)
4 changes: 3 additions & 1 deletion ui/public/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
"dhcp-server_invalid_type": "Number required",
"dhcp-server_number_gte": "Enter a positive number",
"dns-server_format": "IPv4 format required",
"dns-server_number_one_of": "IPv4 or IPv6 required"
"dns-server_number_one_of": "IPv4 or IPv6 required",
"dns_server_is_running": "A DNS server is currently running",
"dns_server_is_running_description": "You cannot enable the DNS feature because a DNS server is already active on this node. Another application, such as Samba DC, might be using the DNS port."
},
"dns_records": {
"title": "DNS records",
Expand Down
25 changes: 24 additions & 1 deletion ui/src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,28 @@
<div class="title-description mg-bottom-xlg">
{{ $t("settings.DNS_description") }}
</div>
<cv-row
v-if="is_dns_bound && !dnsEnableField && !is_dns_enabled"
>
<cv-column>
<NsInlineNotification
kind="info"
:title="$t('settings.dns_server_is_running')"
:description="
$t('settings.dns_server_is_running_description')
"
:showCloseButton="false"
/>
</cv-column>
</cv-row>
<NsToggle
:label="$t('settings.DNS_enable_label')"
v-model="dnsEnableField"
value="dnsEnableField"
formItem
:disabled="
is_dns_bound && !dnsEnableField && !is_dns_enabled
"
ref="dnsEnableField"
>
<template slot="text-left">{{
Expand Down Expand Up @@ -201,7 +218,9 @@
:icon="Save20"
:loading="loading.configureModule"
:disabled="
loading.getConfiguration || loading.configureModule
loading.getConfiguration ||
loading.configureModule ||
(is_dns_bound && !dnsEnableField && !is_dns_enabled)
"
>{{ $t("settings.save") }}</NsButton
>
Expand Down Expand Up @@ -250,6 +269,8 @@ export default {
dhcpStartField: "",
dhcpEndField: "",
dhcpLeaseField: 12,
is_dns_bound: false,
is_dns_enabled: false,
dnsEnableField: false,
dnsPrimaryField: "",
dnsSecondaryField: "",
Expand Down Expand Up @@ -406,6 +427,8 @@ export default {
this.dnsEnableField = dns_server["enabled"];
this.dnsPrimaryField = dns_server["primary-server"];
this.dnsSecondaryField = dns_server["secondary-server"];
this.is_dns_bound = config["is_dns_bound"];
this.is_dns_enabled = config["is_dns_enabled"];
},
validateConfigureModule() {
this.clearErrors(this);
Expand Down

0 comments on commit 3c4d6dc

Please sign in to comment.