summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.service.xml5
-rw-r--r--src/libsystemd/sd-bus/bus-match.c3
-rw-r--r--src/resolve/resolved-manager.c5
-rw-r--r--src/systemctl/systemctl.c50
-rwxr-xr-xtest/networkd-test.py31
5 files changed, 91 insertions, 3 deletions
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 6e969abc25..70f12b2d32 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -202,8 +202,9 @@
notification message has been sent. If this option is used,
<varname>NotifyAccess=</varname> (see below) should be set to
open access to the notification socket provided by systemd. If
- <varname>NotifyAccess=</varname> is not set, it will be
- implicitly set to <option>main</option>. Note that currently
+ <varname>NotifyAccess=</varname> is missing or set to
+ <option>none</option>, it will be forcibly set to
+ <option>main</option>. Note that currently
<varname>Type=</varname><option>notify</option> will not work
if used in combination with
<varname>PrivateNetwork=</varname><option>yes</option>.</para>
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index 397baf6f33..db01f21135 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -429,6 +429,9 @@ int bus_match_run(
r = bus_match_run(bus, c, m);
if (r != 0)
return r;
+
+ if (bus && bus->match_callbacks_modified)
+ return 0;
}
}
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index add463b6a9..92ade820ac 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -1200,6 +1200,11 @@ int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
return 0;
}
+/* filter_route is a tri-state:
+ * < 0: no filtering
+ * = 0 or false: return only domains which should be used for searching
+ * > 0 or true: return only domains which are for routing only
+ */
int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) {
DnsSearchDomain *d;
Iterator i;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index c0b285b58f..b575437bcb 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4367,7 +4367,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
- print_prop("EnvironmentFile", "%s (ignore_errors=%s)\n", path, yes_no(ignore));
+ print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path, yes_no(ignore));
if (r < 0)
return bus_log_parse_error(r);
@@ -5605,6 +5605,46 @@ static int mangle_names(char **original_names, char ***mangled_names) {
return 0;
}
+static int unit_exists(const char *unit) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *path = NULL;
+ static const struct bus_properties_map property_map[] = {
+ { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) },
+ { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)},
+ {},
+ };
+ UnitStatusInfo info = {};
+ sd_bus *bus;
+ int r;
+
+ path = unit_dbus_path_from_name(unit);
+ if (!path)
+ return log_oom();
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ &error,
+ &reply,
+ "s", "");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
+
+ r = bus_message_map_all_properties(reply, property_map, &info);
+ if (r < 0)
+ return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
+
+ return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
+}
+
static int enable_unit(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **names = NULL;
const char *verb = argv[0];
@@ -5666,6 +5706,14 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
const char *method;
sd_bus *bus;
+ if (STR_IN_SET(verb, "mask", "unmask")) {
+ r = unit_exists(*names);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ log_notice("Unit %s does not exist, proceeding anyway.", *names);
+ }
+
r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0)
return r;
diff --git a/test/networkd-test.py b/test/networkd-test.py
index 78da0a213a..8f5d43bc88 100755
--- a/test/networkd-test.py
+++ b/test/networkd-test.py
@@ -227,6 +227,37 @@ DHCP=%s
def test_hotplug_dhcp_ip6(self):
self.do_test(coldplug=False, ipv6=True)
+ def test_route_only_dns(self):
+ with open('/run/systemd/network/myvpn.netdev', 'w') as f:
+ f.write('''[NetDev]
+Name=dummy0
+Kind=dummy
+MACAddress=12:34:56:78:9a:bc''')
+ with open('/run/systemd/network/myvpn.network', 'w') as f:
+ f.write('''[Match]
+Name=dummy0
+[Network]
+Address=192.168.42.100
+DNS=192.168.42.1
+Domains= ~company''')
+ self.addCleanup(os.remove, '/run/systemd/network/myvpn.netdev')
+ self.addCleanup(os.remove, '/run/systemd/network/myvpn.network')
+
+ self.do_test(coldplug=True, ipv6=False,
+ extra_opts='IPv6AcceptRouterAdvertisements=False')
+
+ if os.path.islink('/etc/resolv.conf'):
+ with open('/etc/resolv.conf') as f:
+ contents = f.read()
+
+ # ~company is not a search domain, only a routing domain
+ self.assertNotRegex(contents, 'search.*company')
+
+ # our global server should appear, unless we already have three
+ # (different) servers
+ if contents.count('nameserver ') < 3:
+ self.assertIn('nameserver 192.168.5.1\n', contents)
+
@unittest.skipUnless(have_dnsmasq, 'dnsmasq not installed')
class DnsmasqClientTest(ClientTestBase, unittest.TestCase):