mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #4710 from martinpitt/networkd-dbus
networkd: allow networkd to start in early boot
This commit is contained in:
commit
bbe16abb61
18
Makefile.am
18
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
|
||||
|
@ -1,4 +0,0 @@
|
||||
[Allow systemd-networkd to set transient hostname]
|
||||
Identity=unix-user:systemd-network
|
||||
Action=org.freedesktop.hostname1.set-hostname
|
||||
ResultAny=yes
|
@ -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;
|
||||
}
|
||||
});
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
4
src/network/systemd-networkd.pkla
Normal file
4
src/network/systemd-networkd.pkla
Normal file
@ -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
|
8
src/network/systemd-networkd.rules
Normal file
8
src/network/systemd-networkd.rules
Normal file
@ -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;
|
||||
}
|
||||
});
|
@ -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))
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user