Merge branch 'c8' into a8
This commit is contained in:
commit
d9e6887f0f
@ -1,2 +1,2 @@
|
|||||||
15dc1976653f17d290b65007a4779e3f4ac1833e SOURCES/chrony-4.1.tar.gz
|
0f5de043b395311a58bcf4be9800f7118afd5f59 SOURCES/chrony-4.2.tar.gz
|
||||||
6f953389765ec334465ebdef4199e25c0290646e SOURCES/clknetsim-f89702.tar.gz
|
2e1fac8161ea8d92d76532c0b272fb31799bc310 SOURCES/clknetsim-824c48.tar.gz
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
SOURCES/chrony-4.1.tar.gz
|
SOURCES/chrony-4.2.tar.gz
|
||||||
SOURCES/clknetsim-f89702.tar.gz
|
SOURCES/clknetsim-824c48.tar.gz
|
||||||
|
108
SOURCES/chrony-ipsourcename.patch
Normal file
108
SOURCES/chrony-ipsourcename.patch
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
commit 33a1fe7a9ce223d6287ab7b11bca3208e9255cdd
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Wed Mar 9 15:30:16 2022 +0100
|
||||||
|
|
||||||
|
ntp: split out conf_id allocation
|
||||||
|
|
||||||
|
diff --git a/ntp_sources.c b/ntp_sources.c
|
||||||
|
index 3cbb2ae7..30770825 100644
|
||||||
|
--- a/ntp_sources.c
|
||||||
|
+++ b/ntp_sources.c
|
||||||
|
@@ -698,21 +698,25 @@ static int get_unused_pool_id(void)
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
|
-NSR_Status
|
||||||
|
-NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
||||||
|
- SourceParameters *params, uint32_t *conf_id)
|
||||||
|
+static uint32_t
|
||||||
|
+get_next_conf_id(uint32_t *conf_id)
|
||||||
|
{
|
||||||
|
- NSR_Status s;
|
||||||
|
-
|
||||||
|
- s = add_source(remote_addr, NULL, type, params, INVALID_POOL, last_conf_id + 1);
|
||||||
|
- if (s != NSR_Success)
|
||||||
|
- return s;
|
||||||
|
-
|
||||||
|
last_conf_id++;
|
||||||
|
+
|
||||||
|
if (conf_id)
|
||||||
|
*conf_id = last_conf_id;
|
||||||
|
|
||||||
|
- return s;
|
||||||
|
+ return last_conf_id;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* ================================================== */
|
||||||
|
+
|
||||||
|
+NSR_Status
|
||||||
|
+NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type,
|
||||||
|
+ SourceParameters *params, uint32_t *conf_id)
|
||||||
|
+{
|
||||||
|
+ return add_source(remote_addr, NULL, type, params, INVALID_POOL,
|
||||||
|
+ get_next_conf_id(conf_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
@@ -725,6 +729,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||||
|
struct SourcePool *sp;
|
||||||
|
NTP_Remote_Address remote_addr;
|
||||||
|
int i, new_sources, pool_id;
|
||||||
|
+ uint32_t cid;
|
||||||
|
|
||||||
|
/* If the name is an IP address, add the source with the address directly */
|
||||||
|
if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
|
||||||
|
@@ -770,14 +775,12 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||||
|
|
||||||
|
append_unresolved_source(us);
|
||||||
|
|
||||||
|
- last_conf_id++;
|
||||||
|
- if (conf_id)
|
||||||
|
- *conf_id = last_conf_id;
|
||||||
|
+ cid = get_next_conf_id(conf_id);
|
||||||
|
|
||||||
|
for (i = 0; i < new_sources; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
remote_addr.ip_addr.addr.id = ++last_address_id;
|
||||||
|
- if (add_source(&remote_addr, name, type, params, us->pool_id, last_conf_id) != NSR_Success)
|
||||||
|
+ if (add_source(&remote_addr, name, type, params, us->pool_id, cid) != NSR_Success)
|
||||||
|
return NSR_TooManySources;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
commit 1219f99935ca9597eb0e4f4c6039e536462cf1a6
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Wed Mar 9 15:34:16 2022 +0100
|
||||||
|
|
||||||
|
ntp: keep original source IP address
|
||||||
|
|
||||||
|
When an added source is specified by IP address, save the original
|
||||||
|
string instead of formatting a new string from the parsed address, which
|
||||||
|
can be different (e.g. compressed vs expanded IPv6 address).
|
||||||
|
|
||||||
|
This fixes the chronyc sourcename command and -N option to print the IP
|
||||||
|
address exactly as it was specified in the configuration file or chronyc
|
||||||
|
add command.
|
||||||
|
|
||||||
|
diff --git a/ntp_sources.c b/ntp_sources.c
|
||||||
|
index 30770825..d46c211d 100644
|
||||||
|
--- a/ntp_sources.c
|
||||||
|
+++ b/ntp_sources.c
|
||||||
|
@@ -353,7 +353,6 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type,
|
||||||
|
record_lock = 1;
|
||||||
|
|
||||||
|
record = get_record(slot);
|
||||||
|
- assert(!name || !UTI_IsStringIP(name));
|
||||||
|
record->name = Strdup(name ? name : UTI_IPToString(&remote_addr->ip_addr));
|
||||||
|
record->data = NCR_CreateInstance(remote_addr, type, params, record->name);
|
||||||
|
record->remote_addr = NCR_GetRemoteAddress(record->data);
|
||||||
|
@@ -734,7 +733,8 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type,
|
||||||
|
/* If the name is an IP address, add the source with the address directly */
|
||||||
|
if (UTI_StringToIP(name, &remote_addr.ip_addr)) {
|
||||||
|
remote_addr.port = port;
|
||||||
|
- return NSR_AddSource(&remote_addr, type, params, conf_id);
|
||||||
|
+ return add_source(&remote_addr, name, type, params, INVALID_POOL,
|
||||||
|
+ get_next_conf_id(conf_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the name is at least printable and has no spaces */
|
83
SOURCES/chrony-services.patch
Normal file
83
SOURCES/chrony-services.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
diff --git a/examples/chrony-wait.service b/examples/chrony-wait.service
|
||||||
|
index 72b028f2..b3aa7aa2 100644
|
||||||
|
--- a/examples/chrony-wait.service
|
||||||
|
+++ b/examples/chrony-wait.service
|
||||||
|
@@ -16,32 +16,5 @@ TimeoutStartSec=180
|
||||||
|
RemainAfterExit=yes
|
||||||
|
StandardOutput=null
|
||||||
|
|
||||||
|
-CapabilityBoundingSet=
|
||||||
|
-DevicePolicy=closed
|
||||||
|
-DynamicUser=yes
|
||||||
|
-IPAddressAllow=localhost
|
||||||
|
-IPAddressDeny=any
|
||||||
|
-LockPersonality=yes
|
||||||
|
-MemoryDenyWriteExecute=yes
|
||||||
|
-PrivateDevices=yes
|
||||||
|
-PrivateUsers=yes
|
||||||
|
-ProcSubset=pid
|
||||||
|
-ProtectClock=yes
|
||||||
|
-ProtectControlGroups=yes
|
||||||
|
-ProtectHome=yes
|
||||||
|
-ProtectHostname=yes
|
||||||
|
-ProtectKernelLogs=yes
|
||||||
|
-ProtectKernelModules=yes
|
||||||
|
-ProtectKernelTunables=yes
|
||||||
|
-ProtectProc=invisible
|
||||||
|
-ProtectSystem=strict
|
||||||
|
-RestrictAddressFamilies=AF_INET AF_INET6
|
||||||
|
-RestrictNamespaces=yes
|
||||||
|
-RestrictRealtime=yes
|
||||||
|
-SystemCallArchitectures=native
|
||||||
|
-SystemCallFilter=@system-service
|
||||||
|
-SystemCallFilter=~@privileged @resources
|
||||||
|
-UMask=0777
|
||||||
|
-
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
diff --git a/examples/chronyd.service b/examples/chronyd.service
|
||||||
|
index 4fb930ef..289548cb 100644
|
||||||
|
--- a/examples/chronyd.service
|
||||||
|
+++ b/examples/chronyd.service
|
||||||
|
@@ -10,40 +10,9 @@ Type=forking
|
||||||
|
PIDFile=/run/chrony/chronyd.pid
|
||||||
|
EnvironmentFile=-/etc/sysconfig/chronyd
|
||||||
|
ExecStart=/usr/sbin/chronyd $OPTIONS
|
||||||
|
-
|
||||||
|
-CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
|
||||||
|
-CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
|
||||||
|
-CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_MKNOD CAP_SYS_ADMIN
|
||||||
|
-CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_MODULE CAP_SYS_PACCT
|
||||||
|
-CapabilityBoundingSet=~CAP_SYS_PTRACE CAP_SYS_RAWIO CAP_SYS_TTY_CONFIG CAP_WAKE_ALARM
|
||||||
|
-DeviceAllow=char-pps rw
|
||||||
|
-DeviceAllow=char-ptp rw
|
||||||
|
-DeviceAllow=char-rtc rw
|
||||||
|
-DevicePolicy=closed
|
||||||
|
-LockPersonality=yes
|
||||||
|
-MemoryDenyWriteExecute=yes
|
||||||
|
-NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
-ProcSubset=pid
|
||||||
|
-ProtectControlGroups=yes
|
||||||
|
ProtectHome=yes
|
||||||
|
-ProtectHostname=yes
|
||||||
|
-ProtectKernelLogs=yes
|
||||||
|
-ProtectKernelModules=yes
|
||||||
|
-ProtectKernelTunables=yes
|
||||||
|
-ProtectProc=invisible
|
||||||
|
-ProtectSystem=strict
|
||||||
|
-ReadWritePaths=/run /var/lib/chrony -/var/log
|
||||||
|
-RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||||
|
-RestrictNamespaces=yes
|
||||||
|
-RestrictSUIDSGID=yes
|
||||||
|
-SystemCallArchitectures=native
|
||||||
|
-SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @swap
|
||||||
|
-
|
||||||
|
-# Adjust restrictions for /usr/sbin/sendmail (mailonchange directive)
|
||||||
|
-NoNewPrivileges=no
|
||||||
|
-ReadWritePaths=-/var/spool
|
||||||
|
-RestrictAddressFamilies=AF_NETLINK
|
||||||
|
+ProtectSystem=full
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -20,7 +20,7 @@ dnssrv_timer_prefix=chrony-dnssrv@
|
|||||||
. $network_sysconfig_file &> /dev/null
|
. $network_sysconfig_file &> /dev/null
|
||||||
|
|
||||||
chrony_command() {
|
chrony_command() {
|
||||||
$chronyc -a -n -m "$1"
|
$chronyc -n -m "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
is_running() {
|
is_running() {
|
||||||
@ -70,7 +70,13 @@ update_daemon() {
|
|||||||
|
|
||||||
comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") |
|
comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") |
|
||||||
while read -r server; do
|
while read -r server; do
|
||||||
chrony_command "delete $server" &> /dev/null
|
chrony_command -c sources -a 2>/dev/null |
|
||||||
|
while IFS=, read -r type _ address _; do
|
||||||
|
[ "$type" = "^" ] || continue
|
||||||
|
[ "$(chrony_command "sourcename $address")" = "$server" ] || continue
|
||||||
|
chrony_command "delete $address" &> /dev/null
|
||||||
|
break
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers"))
|
added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers"))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python3
|
||||||
#
|
#
|
||||||
# Convert ntp configuration to chrony
|
# Convert ntp configuration to chrony
|
||||||
#
|
#
|
||||||
@ -28,7 +28,6 @@ import argparse
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@ -39,6 +38,7 @@ if sys.version_info[0] < 3:
|
|||||||
reload(sys)
|
reload(sys)
|
||||||
sys.setdefaultencoding("utf-8")
|
sys.setdefaultencoding("utf-8")
|
||||||
|
|
||||||
|
|
||||||
class NtpConfiguration(object):
|
class NtpConfiguration(object):
|
||||||
def __init__(self, root_dir, ntp_conf, step_tickers):
|
def __init__(self, root_dir, ntp_conf, step_tickers):
|
||||||
self.root_dir = root_dir if root_dir != "/" else ""
|
self.root_dir = root_dir if root_dir != "/" else ""
|
||||||
@ -72,8 +72,9 @@ class NtpConfiguration(object):
|
|||||||
|
|
||||||
def detect_enabled_services(self):
|
def detect_enabled_services(self):
|
||||||
for service in ["ntpdate", "ntpd", "ntp-wait"]:
|
for service in ["ntpdate", "ntpd", "ntp-wait"]:
|
||||||
if os.path.islink("{}/etc/systemd/system/multi-user.target.wants/{}.service"
|
service_path = os.path.join(self.root_dir,
|
||||||
.format(self.root_dir, service)):
|
"etc/systemd/system/multi-user.target.wants/{}.service".format(service))
|
||||||
|
if os.path.islink(service_path):
|
||||||
self.enabled_services.add(service)
|
self.enabled_services.add(service)
|
||||||
logging.info("Enabled services found in /etc/systemd/system: %s",
|
logging.info("Enabled services found in /etc/systemd/system: %s",
|
||||||
" ".join(self.enabled_services))
|
" ".join(self.enabled_services))
|
||||||
@ -255,7 +256,12 @@ class NtpConfiguration(object):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if mask:
|
if mask:
|
||||||
networks.append(ipaddress.ip_network(u"{}/{}".format(address, mask)))
|
# Count bits in the mask (ipaddress does not support
|
||||||
|
# expanded IPv6 netmasks)
|
||||||
|
mask_ip = ipaddress.ip_address(mask)
|
||||||
|
mask_str = "{0:0{1}b}".format(int(mask_ip), mask_ip.max_prefixlen)
|
||||||
|
networks.append(ipaddress.ip_network(
|
||||||
|
u"{}/{}".format(address, len(mask_str.rstrip('0')))))
|
||||||
else:
|
else:
|
||||||
networks.append(ipaddress.ip_network(address))
|
networks.append(ipaddress.ip_network(address))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -490,11 +496,11 @@ class NtpConfiguration(object):
|
|||||||
orphan_stratum = self.tos_options["orphan"]
|
orphan_stratum = self.tos_options["orphan"]
|
||||||
|
|
||||||
if "clockstats" in self.statistics:
|
if "clockstats" in self.statistics:
|
||||||
logs.append("refclocks");
|
logs.append("refclocks")
|
||||||
if "loopstats" in self.statistics:
|
if "loopstats" in self.statistics:
|
||||||
logs.append("tracking")
|
logs.append("tracking")
|
||||||
if "peerstats" in self.statistics:
|
if "peerstats" in self.statistics:
|
||||||
logs.append("statistics");
|
logs.append("statistics")
|
||||||
if "rawstats" in self.statistics:
|
if "rawstats" in self.statistics:
|
||||||
logs.append("measurements")
|
logs.append("measurements")
|
||||||
|
|
||||||
@ -593,6 +599,8 @@ class NtpConfiguration(object):
|
|||||||
|
|
||||||
if key_type in ["m", "M"]:
|
if key_type in ["m", "M"]:
|
||||||
key_type = "MD5"
|
key_type = "MD5"
|
||||||
|
elif key_type == "AES128CMAC":
|
||||||
|
key_type = "AES128"
|
||||||
elif key_type not in ["MD5", "SHA1", "SHA256", "SHA384", "SHA512"]:
|
elif key_type not in ["MD5", "SHA1", "SHA256", "SHA384", "SHA512"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -667,5 +675,6 @@ def main():
|
|||||||
|
|
||||||
conf.write_chrony_configuration(args.chrony_conf, args.chrony_keys, args.dry_run, args.backup)
|
conf.write_chrony_configuration(args.chrony_conf, args.chrony_keys, args.dry_run, args.backup)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
%global clknetsim_ver f89702
|
%global clknetsim_ver 824c48
|
||||||
%global ntp2chrony_ver 2a0512
|
%global ntp2chrony_ver 233b75
|
||||||
%bcond_without debug
|
%bcond_without debug
|
||||||
%bcond_without nts
|
%bcond_without nts
|
||||||
|
|
||||||
Name: chrony
|
Name: chrony
|
||||||
Version: 4.1
|
Version: 4.2
|
||||||
Release: 1%{?dist}.alma
|
Release: 1%{?dist}.alma
|
||||||
Summary: An NTP client/server
|
Summary: An NTP client/server
|
||||||
|
|
||||||
@ -23,6 +23,8 @@ Source10: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/c
|
|||||||
Source11: https://github.com/mlichvar/ntp2chrony/raw/%{ntp2chrony_ver}/ntp2chrony/ntp2chrony.py
|
Source11: https://github.com/mlichvar/ntp2chrony/raw/%{ntp2chrony_ver}/ntp2chrony/ntp2chrony.py
|
||||||
%{?gitpatch:Patch0: chrony-%{version}%{?prerelease}-%{gitpatch}.patch.gz}
|
%{?gitpatch:Patch0: chrony-%{version}%{?prerelease}-%{gitpatch}.patch.gz}
|
||||||
|
|
||||||
|
# revert upstream changes in packaged service files
|
||||||
|
Patch0: chrony-services.patch
|
||||||
# modify NetworkManager DHCP dispatcher to work with chrony-helper and
|
# modify NetworkManager DHCP dispatcher to work with chrony-helper and
|
||||||
# follow distribution-specific configuration
|
# follow distribution-specific configuration
|
||||||
Patch1: chrony-nm-dispatcher-dhcp.patch
|
Patch1: chrony-nm-dispatcher-dhcp.patch
|
||||||
@ -30,6 +32,8 @@ Patch1: chrony-nm-dispatcher-dhcp.patch
|
|||||||
Patch2: chrony-service-helper.patch
|
Patch2: chrony-service-helper.patch
|
||||||
# revert upstream changes in packaged chrony.conf example
|
# revert upstream changes in packaged chrony.conf example
|
||||||
Patch3: chrony-defconfig.patch
|
Patch3: chrony-defconfig.patch
|
||||||
|
# fix chronyc sourcename command to print IP address in original format
|
||||||
|
Patch4: chrony-ipsourcename.patch
|
||||||
|
|
||||||
BuildRequires: libcap-devel libedit-devel nettle-devel pps-tools-devel
|
BuildRequires: libcap-devel libedit-devel nettle-devel pps-tools-devel
|
||||||
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
|
%ifarch %{ix86} x86_64 %{arm} aarch64 mipsel mips64el ppc64 ppc64le s390 s390x
|
||||||
@ -62,9 +66,11 @@ service to other computers in the network.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
|
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
|
||||||
%{?gitpatch:%patch0 -p1}
|
%{?gitpatch:%patch0 -p1}
|
||||||
|
%patch0 -p1 -b .services
|
||||||
%patch1 -p1 -b .nm-dispatcher-dhcp
|
%patch1 -p1 -b .nm-dispatcher-dhcp
|
||||||
%patch2 -p1 -b .service-helper
|
%patch2 -p1 -b .service-helper
|
||||||
%patch3 -p1 -b .defconfig
|
%patch3 -p1 -b .defconfig
|
||||||
|
%patch4 -p1 -b .ipsourcename
|
||||||
|
|
||||||
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
|
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
|
||||||
|
|
||||||
@ -213,9 +219,13 @@ fi
|
|||||||
%dir %attr(750,chrony,chrony) %{_localstatedir}/log/chrony
|
%dir %attr(750,chrony,chrony) %{_localstatedir}/log/chrony
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Fri Oct 08 2021 Andrew Lukoshko <alukoshko@almalinux.org> - 4.1-1.alma
|
* Tue Nov 08 2022 Andrew Lukoshko <alukoshko@almalinux.org> - 4.2-1.alma
|
||||||
- use cloudlinux ntp pool
|
- use cloudlinux ntp pool
|
||||||
|
|
||||||
|
* Thu Jul 14 2022 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
|
||||||
|
- update to 4.2 (#2062356)
|
||||||
|
- fix chrony-helper to delete sources by their original name (#2061660)
|
||||||
|
- update ntp2chrony script (#2018045 #2063766)
|
||||||
* Tue Jun 15 2021 Miroslav Lichvar <mlichvar@redhat.com> 4.1-1
|
* Tue Jun 15 2021 Miroslav Lichvar <mlichvar@redhat.com> 4.1-1
|
||||||
- update to 4.1 (#1895003 #1847853 #1929157)
|
- update to 4.1 (#1895003 #1847853 #1929157)
|
||||||
- add NetworkManager dispatcher script to add servers from DHCP even without
|
- add NetworkManager dispatcher script to add servers from DHCP even without
|
||||||
|
Loading…
Reference in New Issue
Block a user