summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am18
-rw-r--r--src/hostname/systemd-networkd-hostname.pkla4
-rw-r--r--src/hostname/systemd-networkd-hostname.rules5
-rw-r--r--src/network/networkd-dhcp4.c6
-rw-r--r--src/network/networkd-link.c103
-rw-r--r--src/network/networkd-link.h2
-rw-r--r--src/network/networkd-manager.c108
-rw-r--r--src/network/networkd-manager.h5
-rw-r--r--src/network/systemd-networkd.pkla4
-rw-r--r--src/network/systemd-networkd.rules8
-rwxr-xr-xtest/networkd-test.py32
-rw-r--r--units/systemd-networkd.service.m4.in5
12 files changed, 169 insertions, 131 deletions
diff --git a/Makefile.am b/Makefile.am
index 10ce363347..3aeb7b9ae2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4840,16 +4840,8 @@ endif
polkitpolicy_in_files += \
src/hostname/org.freedesktop.hostname1.policy.in
-polkitrules_files += \
- src/hostname/systemd-networkd-hostname.rules
-
-polkitpkla_files += \
- src/hostname/systemd-networkd-hostname.pkla
-
EXTRA_DIST += \
- units/systemd-hostnamed.service.in \
- src/hostname/systemd-networkd-hostname.rules \
- src/hostname/systemd-networkd-hostname.pkla
+ units/systemd-hostnamed.service.in
# ------------------------------------------------------------------------------
dist_systemunit_DATA_busnames += \
@@ -5785,6 +5777,12 @@ SYSTEM_UNIT_ALIASES += \
BUSNAMES_TARGET_WANTS += \
org.freedesktop.network1.busname
+polkitrules_files += \
+ src/network/systemd-networkd.rules
+
+polkitpkla_files += \
+ src/network/systemd-networkd.pkla
+
endif
gperf_gperf_sources += \
@@ -5793,6 +5791,8 @@ gperf_gperf_sources += \
src/network/netdev/netdev-gperf.gperf
EXTRA_DIST += \
+ src/network/systemd-networkd.rules \
+ src/network/systemd-networkd.pkla \
units/systemd-networkd.service.m4.in \
units/systemd-networkd-wait-online.service.in \
test/networkd-test.py
diff --git a/src/hostname/systemd-networkd-hostname.pkla b/src/hostname/systemd-networkd-hostname.pkla
deleted file mode 100644
index 345ce617c6..0000000000
--- a/src/hostname/systemd-networkd-hostname.pkla
+++ /dev/null
@@ -1,4 +0,0 @@
-[Allow systemd-networkd to set transient hostname]
-Identity=unix-user:systemd-network
-Action=org.freedesktop.hostname1.set-hostname
-ResultAny=yes
diff --git a/src/hostname/systemd-networkd-hostname.rules b/src/hostname/systemd-networkd-hostname.rules
deleted file mode 100644
index b7b780da9e..0000000000
--- a/src/hostname/systemd-networkd-hostname.rules
+++ /dev/null
@@ -1,5 +0,0 @@
-polkit.addRule(function(action, subject) {
- if (action.id == "org.freedesktop.hostname1.set-hostname" && subject.user == "systemd-network") {
- return polkit.Result.YES;
- }
-});
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index ca23c1c2a7..c5c5b95c8f 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -255,7 +255,7 @@ static int dhcp_lease_lost(Link *link) {
if (hostname) {
/* If a hostname was set due to the lease, then unset it now. */
- r = link_set_hostname(link, NULL);
+ r = manager_set_hostname(link->manager, NULL);
if (r < 0)
log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
}
@@ -439,7 +439,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
if (hostname) {
- r = link_set_hostname(link, hostname);
+ r = manager_set_hostname(link->manager, hostname);
if (r < 0)
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
}
@@ -451,7 +451,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
if (tz) {
- r = link_set_timezone(link, tz);
+ r = manager_set_timezone(link->manager, tz);
if (r < 0)
log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index b38eec1ba7..cb7df633b7 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1175,109 +1175,6 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
return 0;
}
-static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- _cleanup_link_unref_ Link *link = userdata;
- const sd_bus_error *e;
-
- assert(m);
- assert(link);
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
-
- e = sd_bus_message_get_error(m);
- if (e)
- log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
-
- return 1;
-}
-
-int link_set_hostname(Link *link, const char *hostname) {
- int r;
-
- assert(link);
- assert(link->manager);
-
- log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
-
- if (!link->manager->bus) {
- /* TODO: replace by assert when we can rely on kdbus */
- log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
- return 0;
- }
-
- r = sd_bus_call_method_async(
- link->manager->bus,
- NULL,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
- "SetHostname",
- set_hostname_handler,
- link,
- "sb",
- hostname,
- false);
-
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set transient hostname: %m");
-
- link_ref(link);
-
- return 0;
-}
-
-static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- _cleanup_link_unref_ Link *link = userdata;
- const sd_bus_error *e;
-
- assert(m);
- assert(link);
-
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
- return 1;
-
- e = sd_bus_message_get_error(m);
- if (e)
- log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
-
- return 1;
-}
-
-int link_set_timezone(Link *link, const char *tz) {
- int r;
-
- assert(link);
- assert(link->manager);
- assert(tz);
-
- log_link_debug(link, "Setting system timezone: '%s'", tz);
-
- if (!link->manager->bus) {
- log_link_info(link, "Not connected to system bus, ignoring timezone.");
- return 0;
- }
-
- r = sd_bus_call_method_async(
- link->manager->bus,
- NULL,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetTimezone",
- set_timezone_handler,
- link,
- "sb",
- tz,
- false);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not set timezone: %m");
-
- link_ref(link);
-
- return 0;
-}
-
static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 77f72d070e..e6190fbe57 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -159,8 +159,6 @@ bool link_has_carrier(Link *link);
int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
int link_set_mtu(Link *link, uint32_t mtu);
-int link_set_hostname(Link *link, const char *hostname);
-int link_set_timezone(Link *link, const char *timezone);
int ipv4ll_configure(Link *link);
int dhcp4_configure(Link *link);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index c3d3f48a3f..4e3f9e35c6 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -192,6 +192,18 @@ int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
+ /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
+ if (m->dynamic_hostname) {
+ r = manager_set_hostname(m, m->dynamic_hostname);
+ if (r < 0)
+ return r;
+ }
+ if (m->dynamic_timezone) {
+ r = manager_set_timezone(m, m->dynamic_timezone);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
@@ -1119,6 +1131,9 @@ void manager_free(Manager *m) {
sd_bus_slot_unref(m->prepare_for_sleep_slot);
sd_event_source_unref(m->bus_retry_event_source);
+ free(m->dynamic_timezone);
+ free(m->dynamic_hostname);
+
free(m);
}
@@ -1365,3 +1380,96 @@ void manager_dirty(Manager *manager) {
/* the serialized state in /run is no longer up-to-date */
manager->dirty = true;
}
+
+static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ Manager *manager = userdata;
+ const sd_bus_error *e;
+
+ assert(m);
+ assert(manager);
+
+ e = sd_bus_message_get_error(m);
+ if (e)
+ log_warning_errno(sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
+
+ return 1;
+}
+
+int manager_set_hostname(Manager *m, const char *hostname) {
+ int r;
+
+ log_debug("Setting transient hostname: '%s'", strna(hostname));
+ if (free_and_strdup(&m->dynamic_hostname, hostname) < 0)
+ return log_oom();
+
+ if (!m->bus) {
+ /* TODO: replace by assert when we can rely on kdbus */
+ log_info("Not connected to system bus, ignoring transient hostname.");
+ return 0;
+ }
+
+ r = sd_bus_call_method_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ "SetHostname",
+ set_hostname_handler,
+ m,
+ "sb",
+ hostname,
+ false);
+
+ if (r < 0)
+ return log_error_errno(r, "Could not set transient hostname: %m");
+
+ return 0;
+}
+
+static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ Manager *manager = userdata;
+ const sd_bus_error *e;
+
+ assert(m);
+ assert(manager);
+
+ e = sd_bus_message_get_error(m);
+ if (e)
+ log_warning_errno(sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
+
+ return 1;
+}
+
+int manager_set_timezone(Manager *m, const char *tz) {
+ int r;
+
+ assert(m);
+ assert(tz);
+
+ log_debug("Setting system timezone: '%s'", tz);
+ if (free_and_strdup(&m->dynamic_timezone, tz) < 0)
+ return log_oom();
+
+ if (!m->bus) {
+ log_info("Not connected to system bus, ignoring timezone.");
+ return 0;
+ }
+
+ r = sd_bus_call_method_async(
+ m->bus,
+ NULL,
+ "org.freedesktop.timedate1",
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ "SetTimezone",
+ set_timezone_handler,
+ m,
+ "sb",
+ tz,
+ false);
+ if (r < 0)
+ return log_error_errno(r, "Could not set timezone: %m");
+
+ return 0;
+}
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index a90d9a933f..c81f5057b7 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -63,6 +63,8 @@ struct Manager {
usec_t network_dirs_ts_usec;
DUID duid;
+ char* dynamic_hostname;
+ char* dynamic_timezone;
};
static inline const DUID* link_duid(const Link *link) {
@@ -97,5 +99,8 @@ int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, uni
Link* manager_find_uplink(Manager *m, Link *exclude);
+int manager_set_hostname(Manager *m, const char *hostname);
+int manager_set_timezone(Manager *m, const char *timezone);
+
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
#define _cleanup_manager_free_ _cleanup_(manager_freep)
diff --git a/src/network/systemd-networkd.pkla b/src/network/systemd-networkd.pkla
new file mode 100644
index 0000000000..fb257d933b
--- /dev/null
+++ b/src/network/systemd-networkd.pkla
@@ -0,0 +1,4 @@
+[Allow systemd-networkd to set timezone and transient hostname]
+Identity=unix-user:systemd-network
+Action=org.freedesktop.hostname1.set-hostname;org.freedesktop.timedate1.set-timezone;
+ResultAny=yes
diff --git a/src/network/systemd-networkd.rules b/src/network/systemd-networkd.rules
new file mode 100644
index 0000000000..2e4bc42bfb
--- /dev/null
+++ b/src/network/systemd-networkd.rules
@@ -0,0 +1,8 @@
+// Allow systemd-networkd to set timezone and transient hostname
+polkit.addRule(function(action, subject) {
+ if ((action.id == "org.freedesktop.hostname1.set-hostname" ||
+ action.id == "org.freedesktop.timedate1.set-timezone") &&
+ subject.user == "systemd-network") {
+ return polkit.Result.YES;
+ }
+});
diff --git a/test/networkd-test.py b/test/networkd-test.py
index a00941095b..84ab6c1b02 100755
--- a/test/networkd-test.py
+++ b/test/networkd-test.py
@@ -469,7 +469,7 @@ class NetworkdClientTest(ClientTestBase, unittest.TestCase):
super().setUp()
self.dnsmasq = None
- def create_iface(self, ipv6=False):
+ def create_iface(self, ipv6=False, dhcpserver_opts=None):
'''Create test interface with DHCP server behind it'''
# run "router-side" networkd in own mount namespace to shield it from
@@ -507,11 +507,13 @@ DHCPServer=yes
PoolOffset=10
PoolSize=50
DNS=192.168.5.1
+%(dhopts)s
EOF
# run networkd as in systemd-networkd.service
exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//; p}')
-''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or ''})
+''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or '',
+ 'dhopts': dhcpserver_opts or ''})
os.fchmod(fd, 0o755)
@@ -642,6 +644,32 @@ DNS=127.0.0.1''')
self.assertIn('nameserver 192.168.42.1\n', contents)
self.assertIn('nameserver 127.0.0.1\n', contents)
+ def test_dhcp_timezone(self):
+ '''networkd sets time zone from DHCP'''
+
+ def get_tz():
+ out = subprocess.check_output(['busctl', 'get-property', 'org.freedesktop.timedate1',
+ '/org/freedesktop/timedate1', 'org.freedesktop.timedate1', 'Timezone'])
+ assert out.startswith(b's "')
+ out = out.strip()
+ assert out.endswith(b'"')
+ return out[3:-1].decode()
+
+ orig_timezone = get_tz()
+ self.addCleanup(subprocess.call, ['timedatectl', 'set-timezone', orig_timezone])
+
+ self.create_iface(dhcpserver_opts='EmitTimezone=yes\nTimezone=Pacific/Honolulu')
+ self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=false\n[DHCP]\nUseTimezone=true', dhcp_mode='ipv4')
+
+ # should have applied the received timezone
+ try:
+ self.assertEqual(get_tz(), 'Pacific/Honolulu')
+ except AssertionError:
+ self.show_journal('systemd-networkd.service')
+ self.show_journal('systemd-hostnamed.service')
+ raise
+
+
if __name__ == '__main__':
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
verbosity=2))
diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in
index a968d8bd45..d1cf3fc133 100644
--- a/units/systemd-networkd.service.m4.in
+++ b/units/systemd-networkd.service.m4.in
@@ -10,9 +10,8 @@ Description=Network Service
Documentation=man:systemd-networkd.service(8)
ConditionCapability=CAP_NET_ADMIN
DefaultDependencies=no
-# dbus.service can be dropped once on kdbus, and systemd-udevd.service can be
-# dropped once tuntap is moved to netlink
-After=systemd-udevd.service dbus.service network-pre.target systemd-sysusers.service systemd-sysctl.service
+# systemd-udevd.service can be dropped once tuntap is moved to netlink
+After=systemd-udevd.service network-pre.target systemd-sysusers.service systemd-sysctl.service
Before=network.target multi-user.target shutdown.target
Conflicts=shutdown.target
Wants=network.target