Compare commits
17 Commits
c1495f8e9d
...
d7b34e3841
Author | SHA1 | Date |
---|---|---|
Yuri Chornoivan | d7b34e3841 | |
Lennart Poettering | 5d043c9fdf | |
Lennart Poettering | cbe952fe1f | |
Luca Boccassi | cda667722c | |
Zbigniew Jędrzejewski-Szmek | 77ecc1aaa5 | |
Zbigniew Jędrzejewski-Szmek | 9389a271b7 | |
Zbigniew Jędrzejewski-Szmek | a240147bdc | |
satmandu | 7f6e342c93 | |
Yu Watanabe | 58e6c62191 | |
Yu Watanabe | 1d596fdec2 | |
Yu Watanabe | 8fc2a5dff4 | |
Yu Watanabe | 290696e512 | |
Yu Watanabe | 921693a0f3 | |
Yu Watanabe | ceaec54a3c | |
Yu Watanabe | f050c94df0 | |
Yu Watanabe | 1419ff0401 | |
Yu Watanabe | cecd68c70f |
25
NEWS
25
NEWS
|
@ -91,6 +91,15 @@ CHANGES WITH 246 in spe:
|
||||||
from the documentation, but will now result in warnings when used,
|
from the documentation, but will now result in warnings when used,
|
||||||
and be converted to "journal" and "journal+console" automatically.
|
and be converted to "journal" and "journal+console" automatically.
|
||||||
|
|
||||||
|
* If the service setting User= is set to the "nobody" user, a warning
|
||||||
|
message is now written to the logs (but the value is nonetheless
|
||||||
|
accepted). Setting User=nobody is unsafe, since the primary purpose
|
||||||
|
of the "nobody" user is to own all files whose owner cannot be mapped
|
||||||
|
locally. It's in particular used by the NFS subsystem and in user
|
||||||
|
namespacing. By running a service under this user's UID it might get
|
||||||
|
read and even write access to all these otherwise unmappable files,
|
||||||
|
which is quite likely a major security problem.
|
||||||
|
|
||||||
* A new kernel command line option systemd.hostname= has been added
|
* A new kernel command line option systemd.hostname= has been added
|
||||||
that allows controlling the hostname that is initialized early during
|
that allows controlling the hostname that is initialized early during
|
||||||
boot.
|
boot.
|
||||||
|
@ -370,6 +379,21 @@ CHANGES WITH 246 in spe:
|
||||||
storage and file system may now be configured explicitly, too, via
|
storage and file system may now be configured explicitly, too, via
|
||||||
the new /etc/systemd/homed.conf configuration file.
|
the new /etc/systemd/homed.conf configuration file.
|
||||||
|
|
||||||
|
* systemd-homed now supports unlocking home directories with FIDO2
|
||||||
|
security tokens that support the 'hmac-secret' extension, in addition
|
||||||
|
to the existing support for PKCS#11 security token unlocking
|
||||||
|
support. Note that many recent hardware security tokens support both
|
||||||
|
interfaces. The FIDO2 support is accessible via homectl's
|
||||||
|
--fido2-device= option.
|
||||||
|
|
||||||
|
* homectl's --pkcs11-uri= setting now accepts two special parameters:
|
||||||
|
if "auto" is specified and only one suitable PKCS#11 security token
|
||||||
|
is plugged in, its URL is automatically determined and enrolled for
|
||||||
|
unlocking the home directory. If "list" is specified a brief table of
|
||||||
|
suitable PKCS#11 security tokens is shown. Similar, the new
|
||||||
|
--fido2-device= option also supports these two special values, for
|
||||||
|
automatically selecting and listing suitable FIDO2 devices.
|
||||||
|
|
||||||
* The /etc/crypttab tmp option now optionally takes an argument
|
* The /etc/crypttab tmp option now optionally takes an argument
|
||||||
selecting the file system to use. Moreover, the default is now
|
selecting the file system to use. Moreover, the default is now
|
||||||
changed from ext2 to ext4.
|
changed from ext2 to ext4.
|
||||||
|
@ -496,7 +520,6 @@ CHANGES WITH 246 in spe:
|
||||||
LogControl1 D-Bus API which allows clients to change log level +
|
LogControl1 D-Bus API which allows clients to change log level +
|
||||||
target of the service during runtime.
|
target of the service during runtime.
|
||||||
|
|
||||||
|
|
||||||
CHANGES WITH 245:
|
CHANGES WITH 245:
|
||||||
|
|
||||||
* A new tool "systemd-repart" has been added, that operates as an
|
* A new tool "systemd-repart" has been added, that operates as an
|
||||||
|
|
12
TODO
12
TODO
|
@ -138,12 +138,12 @@ Features:
|
||||||
|
|
||||||
* homed: support new FS_IOC_ADD_ENCRYPTION_KEY ioctl for setting up fscrypt
|
* homed: support new FS_IOC_ADD_ENCRYPTION_KEY ioctl for setting up fscrypt
|
||||||
|
|
||||||
* busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
|
|
||||||
exists and responds.
|
|
||||||
|
|
||||||
* homed: maybe pre-create ~/.cache as subvol so that it can have separate quota
|
* homed: maybe pre-create ~/.cache as subvol so that it can have separate quota
|
||||||
easily?
|
easily?
|
||||||
|
|
||||||
|
* busctl: maybe expose a verb "ping" for pinging a dbus service to see if it
|
||||||
|
exists and responds.
|
||||||
|
|
||||||
* when systemd-nspawn and suchlike dissect an OS image, and there are multiple
|
* when systemd-nspawn and suchlike dissect an OS image, and there are multiple
|
||||||
root partitions, do an strverscmp() on the partition label and boot
|
root partitions, do an strverscmp() on the partition label and boot
|
||||||
first. That is inspired how sd-boot figures out which kernel to boot, and
|
first. That is inspired how sd-boot figures out which kernel to boot, and
|
||||||
|
@ -343,7 +343,8 @@ Features:
|
||||||
beefing up logind to make pam session close hook synchronous and wait until
|
beefing up logind to make pam session close hook synchronous and wait until
|
||||||
systemd --user is shut down.
|
systemd --user is shut down.
|
||||||
- logind: maybe keep a "busy fd" as long as there's a non-released session around or the user@.service
|
- logind: maybe keep a "busy fd" as long as there's a non-released session around or the user@.service
|
||||||
- maybe make automatic, read-only, time-based reflink-copies of LUKS disk images (think: time machine)
|
- maybe make automatic, read-only, time-based reflink-copies of LUKS disk
|
||||||
|
images (and btrfs snapshots of subvolumes) (think: time machine)
|
||||||
- distinguish destroy / remove (i.e. currently we can unregister a user, unregister+remove their home directory, but not just remove their home directory)
|
- distinguish destroy / remove (i.e. currently we can unregister a user, unregister+remove their home directory, but not just remove their home directory)
|
||||||
- in systemd's PAMName= logic: query passwords with ssh-askpassword, so that we can make "loginctl set-linger" mode work
|
- in systemd's PAMName= logic: query passwords with ssh-askpassword, so that we can make "loginctl set-linger" mode work
|
||||||
- fingerprint authentication, pattern authentication, …
|
- fingerprint authentication, pattern authentication, …
|
||||||
|
@ -359,6 +360,9 @@ Features:
|
||||||
- make slice for users configurable (requires logind rework)
|
- make slice for users configurable (requires logind rework)
|
||||||
- logind: populate auto-login list bus property from PKCS#11 token
|
- logind: populate auto-login list bus property from PKCS#11 token
|
||||||
- when determining state of a LUKS home directory, check DM suspended sysfs file
|
- when determining state of a LUKS home directory, check DM suspended sysfs file
|
||||||
|
- introduce API for "making room", that grows/shrinks home directory
|
||||||
|
according to elastic parameters, discards blocks, and removes additional snapshots. Call it
|
||||||
|
either from UI when disk space gets low
|
||||||
|
|
||||||
* introduce a new per-process uuid, similar to the boot id, the machine id, the
|
* introduce a new per-process uuid, similar to the boot id, the machine id, the
|
||||||
invocation id, that is derived from process creds, specifically a hashed
|
invocation id, that is derived from process creds, specifically a hashed
|
||||||
|
|
|
@ -316,6 +316,10 @@ sensor:modalias:platform:cros-ec-accel:dmi:*:svnGoogle:pnCaroline*
|
||||||
sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*
|
sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*
|
||||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
|
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
|
||||||
|
|
||||||
|
# nocturne board (Google Pixel Slate)
|
||||||
|
sensor:modalias:platform:cros-ec-accel:dmi:*Google_Nocturne*
|
||||||
|
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
# GP-electronic
|
# GP-electronic
|
||||||
#########################################
|
#########################################
|
||||||
|
|
|
@ -1334,7 +1334,7 @@ int safe_fork_full(
|
||||||
|
|
||||||
ppid = getppid();
|
ppid = getppid();
|
||||||
if (ppid == 0)
|
if (ppid == 0)
|
||||||
/* Parent is in a differn't PID namespace. */;
|
/* Parent is in a different PID namespace. */;
|
||||||
else if (ppid != original_pid) {
|
else if (ppid != original_pid) {
|
||||||
log_debug("Parent died early, raising SIGTERM.");
|
log_debug("Parent died early, raising SIGTERM.");
|
||||||
(void) raise(SIGTERM);
|
(void) raise(SIGTERM);
|
||||||
|
|
|
@ -77,7 +77,7 @@ int rdrand(unsigned long *ret) {
|
||||||
* hash functions for its hash tables, with a seed generated randomly. The hash tables
|
* hash functions for its hash tables, with a seed generated randomly. The hash tables
|
||||||
* systemd employs watch the fill level closely and reseed if necessary. This allows use of
|
* systemd employs watch the fill level closely and reseed if necessary. This allows use of
|
||||||
* a low quality RNG initially, as long as it improves should a hash table be under attack:
|
* a low quality RNG initially, as long as it improves should a hash table be under attack:
|
||||||
* the attacker after all needs to to trigger many collisions to exploit it for the purpose
|
* the attacker after all needs to trigger many collisions to exploit it for the purpose
|
||||||
* of DoS, but if doing so improves the seed the attack surface is reduced as the attack
|
* of DoS, but if doing so improves the seed the attack surface is reduced as the attack
|
||||||
* takes place.
|
* takes place.
|
||||||
*
|
*
|
||||||
|
|
|
@ -105,7 +105,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) {
|
||||||
if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
|
if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
/* If there's no embedded NUL byte, then then the size needs to match the whole
|
/* If there's no embedded NUL byte, then the size needs to match the whole
|
||||||
* structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
|
* structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
|
||||||
* and considers both equivalent: getsockname() even extends sockaddr_un beyond its
|
* and considers both equivalent: getsockname() even extends sockaddr_un beyond its
|
||||||
* size if the path is non NUL terminated.)*/
|
* size if the path is non NUL terminated.)*/
|
||||||
|
|
|
@ -1932,11 +1932,19 @@ unsigned manager_dispatch_load_queue(Manager *m) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool manager_unit_cache_needs_refresh(Manager *m, Unit *u) {
|
bool manager_unit_file_maybe_loadable_from_cache(Unit *u) {
|
||||||
assert(m);
|
assert(u);
|
||||||
|
|
||||||
return m->unit_cache_mtime > 0 &&
|
if (u->load_state != UNIT_NOT_FOUND)
|
||||||
(m->unit_cache_mtime > u->fragment_loadtime || !lookup_paths_mtime_good(&m->lookup_paths, m->unit_cache_mtime));
|
return false;
|
||||||
|
|
||||||
|
if (u->manager->unit_cache_mtime == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (u->manager->unit_cache_mtime > u->fragment_loadtime)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !lookup_paths_mtime_good(&u->manager->lookup_paths, u->manager->unit_cache_mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_load_unit_prepare(
|
int manager_load_unit_prepare(
|
||||||
|
@ -1988,7 +1996,7 @@ int manager_load_unit_prepare(
|
||||||
* we need to try again - even if the cache is current, it might have been
|
* we need to try again - even if the cache is current, it might have been
|
||||||
* updated in a different context before we had a chance to retry loading
|
* updated in a different context before we had a chance to retry loading
|
||||||
* this particular unit. */
|
* this particular unit. */
|
||||||
if (ret->load_state == UNIT_NOT_FOUND && manager_unit_cache_needs_refresh(m, ret))
|
if (manager_unit_file_maybe_loadable_from_cache(ret))
|
||||||
ret->load_state = UNIT_STUB;
|
ret->load_state = UNIT_STUB;
|
||||||
else {
|
else {
|
||||||
*_ret = ret;
|
*_ret = ret;
|
||||||
|
|
|
@ -463,6 +463,7 @@ Unit *manager_get_unit(Manager *m, const char *name);
|
||||||
|
|
||||||
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
|
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
|
||||||
|
|
||||||
|
bool manager_unit_file_maybe_loadable_from_cache(Unit *u);
|
||||||
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
|
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
|
||||||
int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
|
int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
|
||||||
int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
|
int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
|
||||||
|
|
|
@ -954,6 +954,24 @@ int transaction_add_job_and_dependencies(
|
||||||
|
|
||||||
if (type != JOB_STOP) {
|
if (type != JOB_STOP) {
|
||||||
r = bus_unit_validate_load_state(unit, e);
|
r = bus_unit_validate_load_state(unit, e);
|
||||||
|
/* The time-based cache allows to start new units without daemon-reload,
|
||||||
|
* but if they are already referenced (because of dependencies or ordering)
|
||||||
|
* then we have to force a load of the fragment. As an optimization, check
|
||||||
|
* first if anything in the usual paths was modified since the last time
|
||||||
|
* the cache was loaded. Also check if the last time an attempt to load the
|
||||||
|
* unit was made was before the most recent cache refresh, so that we know
|
||||||
|
* we need to try again - even if the cache is current, it might have been
|
||||||
|
* updated in a different context before we had a chance to retry loading
|
||||||
|
* this particular unit.
|
||||||
|
* Given building up the transaction is a synchronous operation, attempt
|
||||||
|
* to load the unit immediately. */
|
||||||
|
if (r < 0 && manager_unit_file_maybe_loadable_from_cache(unit)) {
|
||||||
|
unit->load_state = UNIT_STUB;
|
||||||
|
r = unit_load(unit);
|
||||||
|
if (r < 0 || unit->load_state == UNIT_STUB)
|
||||||
|
unit->load_state = UNIT_NOT_FOUND;
|
||||||
|
r = bus_unit_validate_load_state(unit, e);
|
||||||
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,7 +376,7 @@ int sd_dhcp_client_set_client_id(
|
||||||
/* For hardware types, log debug message about unexpected data length.
|
/* For hardware types, log debug message about unexpected data length.
|
||||||
*
|
*
|
||||||
* Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
|
* Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
|
||||||
* last last 8 bytes of the address are stable and suitable to put into
|
* the last 8 bytes of the address are stable and suitable to put into
|
||||||
* the client-id. The caller is advised to account for that. */
|
* the client-id. The caller is advised to account for that. */
|
||||||
if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
|
if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
|
||||||
(type == ARPHRD_INFINIBAND && data_len != 8))
|
(type == ARPHRD_INFINIBAND && data_len != 8))
|
||||||
|
@ -1441,7 +1441,10 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
|
||||||
sd_dhcp_client *client = userdata;
|
sd_dhcp_client *client = userdata;
|
||||||
DHCP_CLIENT_DONT_DESTROY(client);
|
DHCP_CLIENT_DONT_DESTROY(client);
|
||||||
|
|
||||||
client->state = DHCP_STATE_RENEWING;
|
if (client->lease)
|
||||||
|
client->state = DHCP_STATE_RENEWING;
|
||||||
|
else if (client->state != DHCP_STATE_INIT)
|
||||||
|
client->state = DHCP_STATE_INIT_REBOOT;
|
||||||
client->attempt = 0;
|
client->attempt = 0;
|
||||||
|
|
||||||
return client_initialize_time_events(client);
|
return client_initialize_time_events(client);
|
||||||
|
@ -2012,6 +2015,9 @@ int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
|
||||||
assert_return(client, -EINVAL);
|
assert_return(client, -EINVAL);
|
||||||
assert_return(client->fd >= 0, -EINVAL);
|
assert_return(client->fd >= 0, -EINVAL);
|
||||||
|
|
||||||
|
if (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT, DHCP_STATE_STOPPED))
|
||||||
|
return 0;
|
||||||
|
|
||||||
client->start_delay = 0;
|
client->start_delay = 0;
|
||||||
client->attempt = 1;
|
client->attempt = 1;
|
||||||
client->state = DHCP_STATE_RENEWING;
|
client->state = DHCP_STATE_RENEWING;
|
||||||
|
|
|
@ -1489,7 +1489,7 @@ static int client_receive_message(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fallthrough_; /* for Soliciation Rapid Commit option check */
|
_fallthrough_; /* for Solicitation Rapid Commit option check */
|
||||||
case DHCP6_STATE_REQUEST:
|
case DHCP6_STATE_REQUEST:
|
||||||
case DHCP6_STATE_RENEW:
|
case DHCP6_STATE_RENEW:
|
||||||
case DHCP6_STATE_REBIND:
|
case DHCP6_STATE_REBIND:
|
||||||
|
|
|
@ -339,12 +339,12 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
sd_radv_stop(ra, true);
|
sd_radv_stop(ra);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_public_ int sd_radv_stop(sd_radv *ra, bool zero_router_lifetime) {
|
_public_ int sd_radv_stop(sd_radv *ra) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_return(ra, -EINVAL);
|
assert_return(ra, -EINVAL);
|
||||||
|
@ -354,15 +354,11 @@ _public_ int sd_radv_stop(sd_radv *ra, bool zero_router_lifetime) {
|
||||||
|
|
||||||
log_radv("Stopping IPv6 Router Advertisement daemon");
|
log_radv("Stopping IPv6 Router Advertisement daemon");
|
||||||
|
|
||||||
if (zero_router_lifetime) {
|
/* RFC 4861, Section 6.2.5, send at least one Router Advertisement
|
||||||
/* RFC 4861, Section 6.2.5, send at least one Router Advertisement
|
with zero lifetime */
|
||||||
with zero lifetime */
|
r = radv_send(ra, NULL, 0);
|
||||||
r = radv_send(ra, NULL, 0);
|
if (r < 0)
|
||||||
if (r < 0)
|
log_radv_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
|
||||||
log_radv_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
|
|
||||||
else
|
|
||||||
log_radv("Sent last Router Advertisement with router lifetime set to zero");
|
|
||||||
}
|
|
||||||
|
|
||||||
radv_reset(ra);
|
radv_reset(ra);
|
||||||
ra->fd = safe_close(ra->fd);
|
ra->fd = safe_close(ra->fd);
|
||||||
|
|
|
@ -284,7 +284,7 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(sd_radv_stop(ra, true) >= 0);
|
assert_se(sd_radv_stop(ra) >= 0);
|
||||||
test_stopped = true;
|
test_stopped = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include "sd-radv.h"
|
|
||||||
|
|
||||||
#include "sd-dhcp6-client.h"
|
#include "sd-dhcp6-client.h"
|
||||||
|
|
||||||
|
@ -18,6 +17,7 @@
|
||||||
#include "networkd-dhcp6.h"
|
#include "networkd-dhcp6.h"
|
||||||
#include "networkd-link.h"
|
#include "networkd-link.h"
|
||||||
#include "networkd-manager.h"
|
#include "networkd-manager.h"
|
||||||
|
#include "networkd-radv.h"
|
||||||
#include "siphash24.h"
|
#include "siphash24.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
@ -28,7 +28,6 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
|
||||||
static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
|
static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
|
||||||
static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
|
static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
|
||||||
static int dhcp6_prefix_remove_all(Manager *m, Link *link);
|
static int dhcp6_prefix_remove_all(Manager *m, Link *link);
|
||||||
static bool dhcp6_link_has_dhcpv6_prefix(Link *link);
|
|
||||||
static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *prefix,
|
static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *prefix,
|
||||||
uint8_t prefix_len,
|
uint8_t prefix_len,
|
||||||
uint32_t lifetime_preferred,
|
uint32_t lifetime_preferred,
|
||||||
|
@ -78,7 +77,7 @@ static int dhcp6_get_preferred_delegated_prefix(
|
||||||
|
|
||||||
if (subnet_id >= 0) {
|
if (subnet_id >= 0) {
|
||||||
/* If the link has a preference for a particular subnet id try to allocate that */
|
/* If the link has a preference for a particular subnet id try to allocate that */
|
||||||
if ((uint64_t)subnet_id >= n_prefixes)
|
if ((uint64_t) subnet_id >= n_prefixes)
|
||||||
return log_link_debug_errno(link,
|
return log_link_debug_errno(link,
|
||||||
SYNTHETIC_ERRNO(ERANGE),
|
SYNTHETIC_ERRNO(ERANGE),
|
||||||
"subnet id %" PRIi64 " is out of range. Only have %" PRIu64 " subnets.",
|
"subnet id %" PRIi64 " is out of range. Only have %" PRIu64 " subnets.",
|
||||||
|
@ -112,28 +111,24 @@ static int dhcp6_get_preferred_delegated_prefix(
|
||||||
log_link_debug(link, "The requested prefix %s is available. Using it.",
|
log_link_debug(link, "The requested prefix %s is available. Using it.",
|
||||||
strnull(assigned_buf));
|
strnull(assigned_buf));
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
for (uint64_t n = 0; n < n_prefixes; n++) {
|
|
||||||
/* if we do not have an allocation preference just iterate
|
|
||||||
* through the address space and return the first free prefix. */
|
|
||||||
Link* assigned_link = dhcp6_prefix_get(manager, &prefix.in6);
|
|
||||||
|
|
||||||
if (!assigned_link || assigned_link == link) {
|
|
||||||
*ret_addr = prefix.in6;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = in_addr_prefix_next(AF_INET6, &prefix, 64);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link,
|
|
||||||
r,
|
|
||||||
"Can't allocate another prefix. Out of address space?");
|
|
||||||
}
|
|
||||||
|
|
||||||
log_link_warning(link, "Couldn't find a suitable prefix. Ran out of address space.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ERANGE;
|
for (uint64_t n = 0; n < n_prefixes; n++) {
|
||||||
|
/* if we do not have an allocation preference just iterate
|
||||||
|
* through the address space and return the first free prefix. */
|
||||||
|
Link* assigned_link = dhcp6_prefix_get(manager, &prefix.in6);
|
||||||
|
|
||||||
|
if (!assigned_link || assigned_link == link) {
|
||||||
|
*ret_addr = prefix.in6;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = in_addr_prefix_next(AF_INET6, &prefix, 64);
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Can't allocate another prefix. Out of address space?");
|
||||||
|
}
|
||||||
|
|
||||||
|
return log_link_warning_errno(link, SYNTHETIC_ERRNO(ERANGE), "Couldn't find a suitable prefix. Ran out of address space.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) {
|
static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) {
|
||||||
|
@ -159,8 +154,7 @@ static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_lease_information_acquired(sd_dhcp6_client *client,
|
static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, Link *link) {
|
||||||
Link *link) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,34 +162,12 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
|
||||||
uint8_t prefix_len,
|
uint8_t prefix_len,
|
||||||
uint32_t lifetime_preferred,
|
uint32_t lifetime_preferred,
|
||||||
uint32_t lifetime_valid) {
|
uint32_t lifetime_valid) {
|
||||||
sd_radv *radv = link->radv;
|
|
||||||
int r;
|
int r;
|
||||||
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
|
|
||||||
|
|
||||||
r = sd_radv_prefix_new(&p);
|
r = radv_add_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_radv_prefix_set_prefix(p, prefix, prefix_len);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_radv_prefix_set_preferred_lifetime(p, lifetime_preferred);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_radv_prefix_set_valid_lifetime(p, lifetime_valid);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_radv_stop(radv, false);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = sd_radv_add_prefix(radv, p, true);
|
|
||||||
if (r < 0 && r != -EEXIST)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = dhcp6_prefix_add(link->manager, prefix, link);
|
r = dhcp6_prefix_add(link->manager, prefix, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -206,7 +178,7 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd_radv_start(radv);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
|
static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
|
||||||
|
@ -312,14 +284,11 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link,
|
||||||
if (!dhcp6_get_prefix_delegation(link))
|
if (!dhcp6_get_prefix_delegation(link))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dhcp6_link_has_dhcpv6_prefix(link))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (assign_preferred_subnet_id != dhcp6_has_preferred_subnet_id(link))
|
if (assign_preferred_subnet_id != dhcp6_has_preferred_subnet_id(link))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dhcp6_get_preferred_delegated_prefix(manager, link, &prefix.in6, pd_prefix_len,
|
r = dhcp6_get_preferred_delegated_prefix(manager, link, &prefix.in6, pd_prefix_len,
|
||||||
&assigned_prefix.in6);
|
&assigned_prefix.in6);
|
||||||
|
|
||||||
if (assign_preferred_subnet_id && r == -EAGAIN) {
|
if (assign_preferred_subnet_id && r == -EAGAIN) {
|
||||||
/* A link has a preferred subnet_id but that one is
|
/* A link has a preferred subnet_id but that one is
|
||||||
|
@ -1029,20 +998,6 @@ static int dhcp6_prefix_remove_all(Manager *m, Link *link) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dhcp6_link_has_dhcpv6_prefix(Link *link) {
|
|
||||||
Iterator i;
|
|
||||||
Link *l;
|
|
||||||
|
|
||||||
assert(link);
|
|
||||||
assert(link->manager);
|
|
||||||
|
|
||||||
HASHMAP_FOREACH(l, link->manager->dhcp6_prefixes, i)
|
|
||||||
if (link == l)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dhcp6_assign_delegated_prefix(Link *link,
|
static int dhcp6_assign_delegated_prefix(Link *link,
|
||||||
const struct in6_addr *prefix,
|
const struct in6_addr *prefix,
|
||||||
uint8_t prefix_len,
|
uint8_t prefix_len,
|
||||||
|
|
|
@ -840,7 +840,7 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->radv) {
|
if (link->radv) {
|
||||||
k = sd_radv_stop(link->radv, true);
|
k = sd_radv_stop(link->radv);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
|
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,6 +672,37 @@ int radv_configure(Link *link) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
|
||||||
|
uint32_t lifetime_preferred, uint32_t lifetime_valid) {
|
||||||
|
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(link->radv);
|
||||||
|
|
||||||
|
r = sd_radv_prefix_new(&p);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_radv_prefix_set_prefix(p, prefix, prefix_len);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_radv_prefix_set_preferred_lifetime(p, lifetime_preferred);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_radv_prefix_set_valid_lifetime(p, lifetime_valid);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_radv_add_prefix(link->radv, p, true);
|
||||||
|
if (r < 0 && r != -EEXIST)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_radv_dns(
|
int config_parse_radv_dns(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
|
|
@ -52,6 +52,8 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
|
||||||
|
|
||||||
int radv_emit_dns(Link *link);
|
int radv_emit_dns(Link *link);
|
||||||
int radv_configure(Link *link);
|
int radv_configure(Link *link);
|
||||||
|
int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
|
||||||
|
uint32_t lifetime_preferred, uint32_t lifetime_valid);
|
||||||
|
|
||||||
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
|
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
|
||||||
RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
|
RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
|
||||||
|
|
|
@ -39,7 +39,7 @@ const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int qdisc_new(QDiscKind kind, QDisc **ret) {
|
static int qdisc_new(QDiscKind kind, QDisc **ret) {
|
||||||
QDisc *qdisc;
|
_cleanup_(qdisc_freep) QDisc *qdisc = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (kind == _QDISC_KIND_INVALID) {
|
if (kind == _QDISC_KIND_INVALID) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tclass_new(TClassKind kind, TClass **ret) {
|
static int tclass_new(TClassKind kind, TClass **ret) {
|
||||||
TClass *tclass;
|
_cleanup_(tclass_freep) TClass *tclass = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
tclass = malloc0(tclass_vtable[kind]->object_size);
|
tclass = malloc0(tclass_vtable[kind]->object_size);
|
||||||
|
|
|
@ -176,7 +176,7 @@ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret);
|
||||||
int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
||||||
int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
||||||
|
|
||||||
/* Low-level, iterative TLV access. This is for evertyhing else, it iteratively goes through all available TLVs
|
/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs
|
||||||
* (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
|
* (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
|
||||||
int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
|
int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
|
||||||
int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
|
int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "_sd-common.h"
|
#include "_sd-common.h"
|
||||||
|
@ -50,7 +49,7 @@ int sd_radv_detach_event(sd_radv *nd);
|
||||||
sd_event *sd_radv_get_event(sd_radv *ra);
|
sd_event *sd_radv_get_event(sd_radv *ra);
|
||||||
|
|
||||||
int sd_radv_start(sd_radv *ra);
|
int sd_radv_start(sd_radv *ra);
|
||||||
int sd_radv_stop(sd_radv *ra, bool zero_router_lifetime);
|
int sd_radv_stop(sd_radv *ra);
|
||||||
|
|
||||||
int sd_radv_set_ifindex(sd_radv *ra, int interface_index);
|
int sd_radv_set_ifindex(sd_radv *ra, int interface_index);
|
||||||
int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr);
|
int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr);
|
||||||
|
|
|
@ -53,6 +53,33 @@ systemctl start testservice-48.service
|
||||||
|
|
||||||
systemctl is-active testservice-48.service
|
systemctl is-active testservice-48.service
|
||||||
|
|
||||||
|
# Stop and remove, and try again to exercise the transaction setup code path by
|
||||||
|
# having the target pull in the unloaded but available unit
|
||||||
|
systemctl stop testservice-48.service testservice-48.target
|
||||||
|
rm -f /run/systemd/system/testservice-48.service /run/systemd/system/testservice-48.target
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
sleep 3.1
|
||||||
|
|
||||||
|
cat > /run/systemd/system/testservice-48.target <<EOF
|
||||||
|
[Unit]
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
Wants=testservice-48.service
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
systemctl start testservice-48.target
|
||||||
|
|
||||||
|
cat > /run/systemd/system/testservice-48.service <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sleep infinity
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl restart testservice-48.target
|
||||||
|
|
||||||
|
systemctl is-active testservice-48.service
|
||||||
|
|
||||||
echo OK > /testok
|
echo OK > /testok
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
Loading…
Reference in New Issue