1
0
mirror of https://github.com/systemd/systemd synced 2026-04-09 16:44:51 +02:00

Compare commits

..

No commits in common. "bf1e65a4fdb4b13dce6afdbc3ce8d9bbb718322e" and "2ed6297f71a04839f23e460095da126112f5626d" have entirely different histories.

23 changed files with 112 additions and 263 deletions

View File

@ -38,8 +38,8 @@ manager, please consider supporting the following interfaces.
3. Pre-mount `/dev/` as (container private) `tmpfs` for the container and bind 3. Pre-mount `/dev/` as (container private) `tmpfs` for the container and bind
mount some suitable TTY to `/dev/console`. If this is a pty, make sure to not mount some suitable TTY to `/dev/console`. If this is a pty, make sure to not
close the controlling pty master during systemd's lifetime. PID1 will close close the controling pty master during systemd's lifetime. PID1 will close ttys,
ttys, to avoid being killed by SAK. It only opens ttys for the time it to avoid being killed by SAK. It only opens ttys for the time it
actually needs to print something. Also, make sure to create device actually needs to print something. Also, make sure to create device
nodes for `/dev/null`, `/dev/zero`, `/dev/full`, `/dev/random`, nodes for `/dev/null`, `/dev/zero`, `/dev/full`, `/dev/random`,
`/dev/urandom`, `/dev/tty`, `/dev/ptmx` in `/dev/`. It is not necessary to `/dev/urandom`, `/dev/tty`, `/dev/ptmx` in `/dev/`. It is not necessary to

View File

@ -2106,12 +2106,11 @@ Table=1234</programlisting></para>
<listitem> <listitem>
<para>Allows DHCPv6 client to start without router advertisements's managed or other <para>Allows DHCPv6 client to start without router advertisements's managed or other
address configuration flag. Takes one of <literal>no</literal>, <literal>solicit</literal> address configuration flag. Takes one of <literal>no</literal>, <literal>solicit</literal>
or <literal>information-request</literal>. If this is not specified, or <literal>information-request</literal>. When this is not specified and
<literal>solicit</literal> is used when <varname>DHCPv6PrefixDelegation=</varname> is <varname>UplinkInterface=:self</varname> is specified, then <literal>solicit</literal> is
enabled and <varname>UplinkInterface=:self</varname> is specified in the implied. Otherwise, defaults to <literal>no</literal>, and the DHCPv6 client will be
[DHCPv6PrefixDelegation] section. Otherwise, defaults to <literal>no</literal>, and the started when an RA is received. See also <varname>DHCPv6Client=</varname> setting in the
DHCPv6 client will be started when an RA is received. See also [IPv6AcceptRA] section.</para>
<varname>DHCPv6Client=</varname> setting in the [IPv6AcceptRA] section.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
@ -2712,11 +2711,9 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<listitem><para>Specifies the name or the index of the uplink interface, or one of the special <listitem><para>Specifies the name or the index of the uplink interface, or one of the special
values <literal>:none</literal> and <literal>:auto</literal>. When emitting DNS servers or values <literal>:none</literal> and <literal>:auto</literal>. When emitting DNS servers or
search domains is enabled but no servers are specified, the servers configured in the uplink search domains is enabled but no servers are specified, the servers configured in the uplink
interface will be emitted. When <literal>:auto</literal>, the value specified to the same interface will be emitted. When <literal>:auto</literal>, the link which has a default gateway
setting in the [DHCPv6PrefixDelegation] section will be used if with the highest priority will be automatically selected. When <literal>:none</literal>, no
<varname>DHCPv6PrefixDelegation=</varname> is enabled, otherwise the link which has a default uplink interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
gateway with the highest priority will be automatically selected. When <literal>:none</literal>,
no uplink interface will be selected. Defaults to <literal>:auto</literal>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -28,7 +28,7 @@ if efi_arch.length() == 0
if get_option('gnu-efi') == 'true' if get_option('gnu-efi') == 'true'
error('gnu-efi support requested, but headers not found or efi arch is unknown') error('gnu-efi support requested, but headers not found or efi arch is unknown')
endif endif
warning('gnu-efi headers not found or efi arch is unknown, disabling gnu-efi support') warning('gnu-efi headers not found or efi arch is unkown, disabling gnu-efi support')
subdir_done() subdir_done()
endif endif

View File

@ -872,10 +872,7 @@ int bpf_firewall_supported(void) {
/* YAY! */ /* YAY! */
} else { } else {
bpf_firewall_unsupported_reason = log_debug("Wut? Kernel accepted our invalid BPF_PROG_DETACH call? Something is weird, assuming BPF firewalling is broken and hence not supported.");
log_debug_errno(SYNTHETIC_ERRNO(EBADE),
"Wut? Kernel accepted our invalid BPF_PROG_DETACH call? "
"Something is weird, assuming BPF firewalling is broken and hence not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED; return supported = BPF_FIREWALL_UNSUPPORTED;
} }
@ -903,10 +900,7 @@ int bpf_firewall_supported(void) {
return supported = BPF_FIREWALL_SUPPORTED; return supported = BPF_FIREWALL_SUPPORTED;
} else { } else {
bpf_firewall_unsupported_reason = log_debug("Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? Something is weird, assuming BPF firewalling is broken and hence not supported.");
log_debug_errno(SYNTHETIC_ERRNO(EBADE),
"Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? "
"Something is weird, assuming BPF firewalling is broken and hence not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED; return supported = BPF_FIREWALL_UNSUPPORTED;
} }
} }
@ -914,10 +908,7 @@ int bpf_firewall_supported(void) {
void emit_bpf_firewall_warning(Unit *u) { void emit_bpf_firewall_warning(Unit *u) {
static bool warned = false; static bool warned = false;
assert(u); if (!warned) {
assert(u->manager);
if (!warned && !MANAGER_IS_TEST_RUN(u->manager)) {
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container() > 0; bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container() > 0;
log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,

View File

@ -3228,36 +3228,26 @@ static int cg_bpf_mask_supported(CGroupMask *ret) {
/* BPF-based firewall */ /* BPF-based firewall */
r = bpf_firewall_supported(); r = bpf_firewall_supported();
if (r < 0)
return r;
if (r > 0) if (r > 0)
mask |= CGROUP_MASK_BPF_FIREWALL; mask |= CGROUP_MASK_BPF_FIREWALL;
/* BPF-based device access control */ /* BPF-based device access control */
r = bpf_devices_supported(); r = bpf_devices_supported();
if (r < 0)
return r;
if (r > 0) if (r > 0)
mask |= CGROUP_MASK_BPF_DEVICES; mask |= CGROUP_MASK_BPF_DEVICES;
/* BPF pinned prog */ /* BPF pinned prog */
r = bpf_foreign_supported(); r = bpf_foreign_supported();
if (r < 0)
return r;
if (r > 0) if (r > 0)
mask |= CGROUP_MASK_BPF_FOREIGN; mask |= CGROUP_MASK_BPF_FOREIGN;
/* BPF-based bind{4|6} hooks */ /* BPF-based bind{4|6} hooks */
r = bpf_socket_bind_supported(); r = bpf_socket_bind_supported();
if (r < 0)
return r;
if (r > 0) if (r > 0)
mask |= CGROUP_MASK_BPF_SOCKET_BIND; mask |= CGROUP_MASK_BPF_SOCKET_BIND;
/* BPF-based cgroup_skb/{egress|ingress} hooks */ /* BPF-based cgroup_skb/{egress|ingress} hooks */
r = restrict_network_interfaces_supported(); r = restrict_network_interfaces_supported();
if (r < 0)
return r;
if (r > 0) if (r > 0)
mask |= CGROUP_MASK_BPF_RESTRICT_NETWORK_INTERFACES; mask |= CGROUP_MASK_BPF_RESTRICT_NETWORK_INTERFACES;

View File

@ -66,35 +66,41 @@ static int prepare_restrict_ifaces_bpf(Unit* u, bool is_allow_list,
int restrict_network_interfaces_supported(void) { int restrict_network_interfaces_supported(void) {
_cleanup_(restrict_ifaces_bpf_freep) struct restrict_ifaces_bpf *obj = NULL; _cleanup_(restrict_ifaces_bpf_freep) struct restrict_ifaces_bpf *obj = NULL;
static int supported = -1;
int r; int r;
static int supported = -1;
if (supported >= 0) if (supported >= 0)
return supported; return supported;
r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
if (r < 0) if (r < 0) {
return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m");
supported = 0;
return supported;
}
if (r == 0) { if (r == 0) {
log_debug("Not running with unified cgroup hierarchy, BPF is not supported"); log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
return supported = 0; "Not running with unified cgroup hierarchy, BPF is not supported");
supported = 0;
return supported;
} }
if (dlopen_bpf() < 0) if (dlopen_bpf() < 0)
return false; return false;
if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) { if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) {
log_debug("BPF program type cgroup_skb is not supported"); log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
return supported = 0; "BPF program type cgroup_skb is not supported");
supported = 0;
return supported;
} }
r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj); r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj);
if (r < 0) { if (r < 0)
log_debug_errno(r, "Failed to load BPF object: %m"); return log_debug_errno(r, "Failed to load BPF object: %m");
return supported = 0;
}
return supported = bpf_can_link_program(obj->progs.sd_restrictif_i); supported = bpf_can_link_program(obj->progs.sd_restrictif_i);
return supported;
} }
static int restrict_network_interfaces_install_impl(Unit *u) { static int restrict_network_interfaces_install_impl(Unit *u) {

View File

@ -42,28 +42,25 @@ bool link_dhcp6_pd_is_enabled(Link *link) {
return link->network->dhcp6_pd; return link->network->dhcp6_pd;
} }
static bool dhcp6_pd_is_uplink(Link *link, Link *target, bool accept_auto) { static int dhcp6_pd_resolve_uplink(Link *link, Link **ret) {
assert(link);
assert(target);
if (!link_dhcp6_pd_is_enabled(link))
return false;
if (link->network->dhcp6_pd_uplink_name) if (link->network->dhcp6_pd_uplink_name)
return streq_ptr(target->ifname, link->network->dhcp6_pd_uplink_name) || return link_get_by_name(link->manager, link->network->dhcp6_pd_uplink_name, ret);
strv_contains(target->alternative_names, link->network->dhcp6_pd_uplink_name);
if (link->network->dhcp6_pd_uplink_index > 0) if (link->network->dhcp6_pd_uplink_index > 0)
return target->ifindex == link->network->dhcp6_pd_uplink_index; return link_get_by_index(link->manager, link->network->dhcp6_pd_uplink_index, ret);
if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF) if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF) {
return link == target; *ret = link;
return 0;
}
assert(link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_AUTO); assert(link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_AUTO);
return accept_auto; return -ENOENT;
} }
static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) { static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) {
Link *uplink;
assert(link); assert(link);
if (!link->network) if (!link->network)
@ -73,12 +70,11 @@ static DHCP6ClientStartMode link_get_dhcp6_client_start_mode(Link *link) {
if (link->network->dhcp6_client_start_mode >= 0) if (link->network->dhcp6_client_start_mode >= 0)
return link->network->dhcp6_client_start_mode; return link->network->dhcp6_client_start_mode;
/* When this interface itself is an uplink interface, then start dhcp6 client in managed mode. */ if (dhcp6_pd_resolve_uplink(link, &uplink) < 0)
if (dhcp6_pd_is_uplink(link, link, /* accept_auto = */ false)) return DHCP6_CLIENT_START_MODE_NO;
return DHCP6_CLIENT_START_MODE_SOLICIT;
/* Otherwise, start dhcp6 client when RA is received. */ /* When this interface itself is an uplink interface, then start dhcp6 client in managed mode */
return DHCP6_CLIENT_START_MODE_NO; return uplink == link ? DHCP6_CLIENT_START_MODE_SOLICIT : DHCP6_CLIENT_START_MODE_NO;
} }
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
@ -531,20 +527,13 @@ static int dhcp6_pd_get_preferred_prefix(
} }
for (uint64_t n = 0; ; n++) { for (uint64_t n = 0; ; n++) {
/* If we do not have an allocation preference just iterate
* through the address space and return the first free prefix. */
r = dhcp6_pd_calculate_prefix(pd_prefix, pd_prefix_len, n, &prefix); r = dhcp6_pd_calculate_prefix(pd_prefix, pd_prefix_len, n, &prefix);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, return log_link_warning_errno(link, r,
"Couldn't find a suitable prefix. Ran out of address space."); "Couldn't find a suitable prefix. Ran out of address space.");
/* Do not use explicitly requested subnet IDs. Note that the corresponding link may not /* If we do not have an allocation preference just iterate
* appear yet. So, we need to check the ID is not used in any .network files. */ * through the address space and return the first free prefix. */
if (set_contains(link->manager->dhcp6_pd_subnet_ids, &n))
continue;
/* Check that the prefix is not assigned to another link. */
if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix, &assigned_link) < 0 || if (link_get_by_dhcp6_pd_prefix(link->manager, &prefix, &assigned_link) < 0 ||
assigned_link == link) { assigned_link == link) {
*ret = prefix; *ret = prefix;
@ -609,7 +598,8 @@ static int dhcp6_pd_distribute_prefix(
const struct in6_addr *pd_prefix, const struct in6_addr *pd_prefix,
uint8_t pd_prefix_len, uint8_t pd_prefix_len,
usec_t lifetime_preferred_usec, usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) { usec_t lifetime_valid_usec,
bool assign_preferred_subnet_id) {
Link *link; Link *link;
int r; int r;
@ -620,10 +610,12 @@ static int dhcp6_pd_distribute_prefix(
assert(pd_prefix_len <= 64); assert(pd_prefix_len <= 64);
HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) { HASHMAP_FOREACH(link, dhcp6_link->manager->links_by_index) {
Link *uplink;
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
continue; continue;
if (!dhcp6_pd_is_uplink(link, dhcp6_link, /* accept_auto = */ true)) if (!link_dhcp6_pd_is_enabled(link))
continue; continue;
if (link->network->dhcp6_pd_announce && !link->radv) if (link->network->dhcp6_pd_announce && !link->radv)
@ -632,6 +624,18 @@ static int dhcp6_pd_distribute_prefix(
if (link == dhcp6_link && !link->network->dhcp6_pd_assign) if (link == dhcp6_link && !link->network->dhcp6_pd_assign)
continue; continue;
if (assign_preferred_subnet_id != link_has_preferred_subnet_id(link))
continue;
r = dhcp6_pd_resolve_uplink(link, &uplink);
if (r != -ENOENT) {
if (r < 0) /* The uplink interface does not exist yet. */
continue;
if (uplink != dhcp6_link)
continue;
}
r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); r = dhcp6_pd_assign_prefix(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0) { if (r < 0) {
if (link == dhcp6_link) if (link == dhcp6_link)
@ -981,7 +985,17 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
&pd_prefix, &pd_prefix,
pd_prefix_len, pd_prefix_len,
lifetime_preferred_usec, lifetime_preferred_usec,
lifetime_valid_usec); lifetime_valid_usec,
true);
if (r < 0)
return r;
r = dhcp6_pd_distribute_prefix(dhcp6_link,
&pd_prefix,
pd_prefix_len,
lifetime_preferred_usec,
lifetime_valid_usec,
false);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -1438,38 +1452,28 @@ static bool dhcp6_pd_uplink_is_ready(Link *link) {
return dhcp6_lease_has_pd_prefix(link->dhcp6_lease); return dhcp6_lease_has_pd_prefix(link->dhcp6_lease);
} }
int dhcp6_pd_find_uplink(Link *link, Link **ret) { static int dhcp6_pd_find_uplink(Link *link, Link **ret) {
Link *uplink = NULL; Link *l;
int r = 0;
assert(link); assert(link);
assert(link->manager); assert(link->manager);
assert(link_dhcp6_pd_is_enabled(link)); assert(link->network);
assert(ret); assert(ret);
if (link->network->dhcp6_pd_uplink_name) if (dhcp6_pd_resolve_uplink(link, &l) >= 0) {
r = link_get_by_name(link->manager, link->network->dhcp6_pd_uplink_name, &uplink); if (!dhcp6_pd_uplink_is_ready(l))
else if (link->network->dhcp6_pd_uplink_index > 0)
r = link_get_by_index(link->manager, link->network->dhcp6_pd_uplink_index, &uplink);
else if (link->network->dhcp6_pd_uplink_index == UPLINK_INDEX_SELF)
uplink = link;
if (r < 0)
return r;
if (uplink) {
if (!dhcp6_pd_uplink_is_ready(uplink))
return -EBUSY; return -EBUSY;
*ret = uplink; *ret = l;
return 0; return 0;
} }
HASHMAP_FOREACH(uplink, link->manager->links_by_index) { HASHMAP_FOREACH(l, link->manager->links_by_index) {
if (!dhcp6_pd_uplink_is_ready(uplink)) if (!dhcp6_pd_uplink_is_ready(l))
continue; continue;
/* Assume that there exists at most one link which acquired delegated prefixes. */ /* Assume that there exists at most one link which acquired delegated prefixes. */
*ret = uplink; *ret = l;
return 0; return 0;
} }

View File

@ -18,7 +18,6 @@ typedef struct Request Request;
bool link_dhcp6_with_address_enabled(Link *link); bool link_dhcp6_with_address_enabled(Link *link);
bool link_dhcp6_pd_is_enabled(Link *link); bool link_dhcp6_pd_is_enabled(Link *link);
int dhcp6_pd_find_uplink(Link *link, Link **ret);
int dhcp6_pd_remove(Link *link, bool only_marked); int dhcp6_pd_remove(Link *link, bool only_marked);
int dhcp6_update_mac(Link *link); int dhcp6_update_mac(Link *link);
int dhcp6_start(Link *link); int dhcp6_start(Link *link);

View File

@ -502,7 +502,6 @@ Manager* manager_free(Manager *m) {
m->links_by_dhcp6_pd_prefix = hashmap_free(m->links_by_dhcp6_pd_prefix); m->links_by_dhcp6_pd_prefix = hashmap_free(m->links_by_dhcp6_pd_prefix);
m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref); m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref);
m->dhcp6_pd_subnet_ids = set_free(m->dhcp6_pd_subnet_ids);
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref); m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref); m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
@ -586,7 +585,7 @@ int manager_load_config(Manager *m) {
if (r < 0) if (r < 0)
return r; return r;
return manager_build_dhcp6_pd_subnet_ids(m); return 0;
} }
bool manager_should_reload(Manager *m) { bool manager_should_reload(Manager *m) {

View File

@ -52,7 +52,6 @@ struct Manager {
Hashmap *netdevs; Hashmap *netdevs;
OrderedHashmap *networks; OrderedHashmap *networks;
OrderedSet *address_pools; OrderedSet *address_pools;
Set *dhcp6_pd_subnet_ids;
usec_t network_dirs_ts_usec; usec_t network_dirs_ts_usec;

View File

@ -643,7 +643,7 @@ int network_reload(Manager *manager) {
ordered_hashmap_free_with_destructor(manager->networks, network_unref); ordered_hashmap_free_with_destructor(manager->networks, network_unref);
manager->networks = new_networks; manager->networks = new_networks;
return manager_build_dhcp6_pd_subnet_ids(manager); return 0;
failure: failure:
ordered_hashmap_free_with_destructor(new_networks, network_unref); ordered_hashmap_free_with_destructor(new_networks, network_unref);
@ -651,32 +651,6 @@ failure:
return r; return r;
} }
int manager_build_dhcp6_pd_subnet_ids(Manager *manager) {
Network *n;
int r;
assert(manager);
set_clear(manager->dhcp6_pd_subnet_ids);
ORDERED_HASHMAP_FOREACH(n, manager->networks) {
if (n->unmanaged)
continue;
if (!n->dhcp6_pd)
continue;
if (n->dhcp6_pd_subnet_id < 0)
continue;
r = set_ensure_put(&manager->dhcp6_pd_subnet_ids, &uint64_hash_ops, &n->dhcp6_pd_subnet_id);
if (r < 0)
return r;
}
return 0;
}
static Network *network_free(Network *network) { static Network *network_free(Network *network) {
if (!network) if (!network)
return NULL; return NULL;

View File

@ -365,8 +365,6 @@ int network_reload(Manager *manager);
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename); int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename);
int network_verify(Network *network); int network_verify(Network *network);
int manager_build_dhcp6_pd_subnet_ids(Manager *manager);
int network_get_by_name(Manager *manager, const char *name, Network **ret); int network_get_by_name(Manager *manager, const char *name, Network **ret);
void network_apply_anonymize_if_set(Network *network); void network_apply_anonymize_if_set(Network *network);

View File

@ -410,8 +410,6 @@ set_domains:
} }
static int radv_find_uplink(Link *link, Link **ret) { static int radv_find_uplink(Link *link, Link **ret) {
int r;
assert(link); assert(link);
if (link->network->router_uplink_name) if (link->network->router_uplink_name)
@ -421,12 +419,8 @@ static int radv_find_uplink(Link *link, Link **ret) {
return link_get_by_index(link->manager, link->network->router_uplink_index, ret); return link_get_by_index(link->manager, link->network->router_uplink_index, ret);
if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) { if (link->network->router_uplink_index == UPLINK_INDEX_AUTO) {
if (link_dhcp6_pd_is_enabled(link)) /* It is not necessary to propagate error in automatic selection. */
r = dhcp6_pd_find_uplink(link, ret); /* When DHCPv6PD is enabled, use its uplink. */ if (manager_find_uplink(link->manager, AF_INET6, link, ret) < 0)
else
r = manager_find_uplink(link->manager, AF_INET6, link, ret);
if (r < 0)
/* It is not necessary to propagate error in automatic selection. */
*ret = NULL; *ret = NULL;
return 0; return 0;
} }

View File

@ -604,11 +604,8 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha
} }
if (r == 0) { if (r == 0) {
/* We want to avoid loops, given this can be called from systemd-coredump */ /* We want to avoid loops, given this can be called from systemd-coredump */
if (fork_disable_dump) { if (fork_disable_dump)
r = RET_NERRNO(prctl(PR_SET_DUMPABLE, 0)); prctl(PR_SET_DUMPABLE, 0);
if (r < 0)
goto child_fail;
}
r = parse_core(fd, executable, ret ? &buf : NULL, ret_package_metadata ? &package_metadata : NULL); r = parse_core(fd, executable, ret ? &buf : NULL, ret_package_metadata ? &package_metadata : NULL);
if (r < 0) if (r < 0)

View File

@ -1,9 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[NetDev]
Name=veth97
Kind=veth
MACAddress=12:34:56:78:9a:ce
[Peer]
Name=veth97-peer
MACAddress=12:34:56:78:9a:cf

View File

@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes
[DHCPv6PrefixDelegation] [DHCPv6PrefixDelegation]
UplinkInterface=veth99 UplinkInterface=veth99
SubnetId=1 SubnetId=6
Announce=no Announce=no
Token=eui64 Token=eui64
Token=::1a:2b:3c:4d Token=::1a:2b:3c:4d

View File

@ -10,7 +10,7 @@ DHCPv6PrefixDelegation=yes
[DHCPv6PrefixDelegation] [DHCPv6PrefixDelegation]
UplinkInterface=veth99 UplinkInterface=veth99
SubnetId=2 SubnetId=3
Announce=no Announce=no
Token=eui64 Token=eui64
Token=::1a:2b:3c:4d Token=::1a:2b:3c:4d

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=veth97-peer
[Network]
IPv6PrivacyExtensions=yes
IPv6AcceptRA=yes
[IPv6AcceptRA]
Token=eui64
Token=::1a:2b:3c:4e

View File

@ -1,20 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
Name=veth97
[Network]
IPv6PrivacyExtensions=yes
IPv6AcceptRA=no
DHCP=no
DHCPv6PrefixDelegation=yes
IPv6SendRA=yes
[DHCPv6PrefixDelegation]
SubnetId=8
Announce=yes
Token=eui64
Token=::1a:2b:3c:4d
[IPv6SendRA]
EmitDNS=no
EmitDomains=no

View File

@ -17,5 +17,6 @@ Token=eui64
Token=::1a:2b:3c:4d Token=::1a:2b:3c:4d
[IPv6SendRA] [IPv6SendRA]
UplinkInterface=:none
EmitDNS=no EmitDNS=no
EmitDomains=no EmitDomains=no

View File

@ -5002,7 +5002,6 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
'dummy98', 'dummy98',
'dummy99', 'dummy99',
'test1', 'test1',
'veth97',
'veth98', 'veth98',
'veth99', 'veth99',
] ]
@ -5012,14 +5011,11 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
'12-dummy.netdev', '12-dummy.netdev',
'13-dummy.netdev', '13-dummy.netdev',
'25-veth.netdev', '25-veth.netdev',
'25-veth-downstream-veth97.netdev', '25-veth-downstream.netdev',
'25-veth-downstream-veth98.netdev',
'dhcp6pd-downstream-dummy97.network', 'dhcp6pd-downstream-dummy97.network',
'dhcp6pd-downstream-dummy98.network', 'dhcp6pd-downstream-dummy98.network',
'dhcp6pd-downstream-dummy99.network', 'dhcp6pd-downstream-dummy99.network',
'dhcp6pd-downstream-test1.network', 'dhcp6pd-downstream-test1.network',
'dhcp6pd-downstream-veth97.network',
'dhcp6pd-downstream-veth97-peer.network',
'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98.network',
'dhcp6pd-downstream-veth98-peer.network', 'dhcp6pd-downstream-veth98-peer.network',
'dhcp6pd-server.network', 'dhcp6pd-server.network',
@ -5039,8 +5035,7 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
def test_dhcp6pd(self): def test_dhcp6pd(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network', copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network',
'25-veth-downstream-veth97.netdev', 'dhcp6pd-downstream-veth97.network', 'dhcp6pd-downstream-veth97-peer.network', '25-veth-downstream.netdev', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network',
'25-veth-downstream-veth98.netdev', 'dhcp6pd-downstream-veth98.network', 'dhcp6pd-downstream-veth98-peer.network',
'11-dummy.netdev', 'dhcp6pd-downstream-test1.network', '11-dummy.netdev', 'dhcp6pd-downstream-test1.network',
'dhcp6pd-downstream-dummy97.network', 'dhcp6pd-downstream-dummy97.network',
'12-dummy.netdev', 'dhcp6pd-downstream-dummy98.network', '12-dummy.netdev', 'dhcp6pd-downstream-dummy98.network',
@ -5050,24 +5045,13 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
self.wait_online(['veth-peer:carrier']) self.wait_online(['veth-peer:carrier'])
start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf') start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf')
self.wait_online(['veth-peer:routable', 'veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded', self.wait_online(['veth-peer:routable', 'veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable']) 'veth98:routable', 'veth98-peer:routable'])
print('### ip -6 address show dev veth-peer scope global') print('### ip -6 address show dev veth-peer scope global')
output = check_output('ip -6 address show dev veth-peer scope global') output = check_output('ip -6 address show dev veth-peer scope global')
print(output) print(output)
self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output) self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output)
'''
Link Subnet IDs
test1: 0x00
dummy97: 0x01 (The link will appear later)
dummy98: 0x02
dummy99: auto -> 0x03 (No address assignment)
veth97: 0x08
veth98: 0x09
veth99: 0x10
'''
print('### ip -6 address show dev veth99 scope global') print('### ip -6 address show dev veth99 scope global')
output = check_output('ip -6 address show dev veth99 scope global') output = check_output('ip -6 address show dev veth99 scope global')
print(output) print(output)
@ -5093,35 +5077,9 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
output = check_output('ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]03:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy99 scope global')
print(output)
# Assign=no
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03')
print('### ip -6 address show dev veth97 scope global')
output = check_output('ip -6 address show dev veth97 scope global')
print(output)
# address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (Token=eui64)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary)
self.wait_address('veth97', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev veth97-peer scope global')
output = check_output('ip -6 address show dev veth97-peer scope global')
print(output)
# NDisc address (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
# NDisc address (Token=eui64)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
# NDisc address (temporary)
self.wait_address('veth97-peer', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev veth98 scope global') print('### ip -6 address show dev veth98 scope global')
output = check_output('ip -6 address show dev veth98 scope global') output = check_output('ip -6 address show dev veth98 scope global')
@ -5143,6 +5101,10 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
# NDisc address (temporary) # NDisc address (temporary)
self.wait_address('veth98-peer', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('veth98-peer', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy98 scope global')
print(output)
print('### ip -6 route show type unreachable') print('### ip -6 route show type unreachable')
output = check_output('ip -6 route show type unreachable') output = check_output('ip -6 route show type unreachable')
print(output) print(output)
@ -5161,22 +5123,12 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
print('### ip -6 route show dev dummy98') print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev dummy99') print('### ip -6 route show dev dummy99')
output = check_output('ip -6 route show dev dummy99') output = check_output('ip -6 route show dev dummy99')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto dhcp metric [0-9]* expires')
print('### ip -6 route show dev veth97')
output = check_output('ip -6 route show dev veth97')
print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev veth97-peer')
output = check_output('ip -6 route show dev veth97-peer')
print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto ra metric [0-9]* expires')
print('### ip -6 route show dev veth98') print('### ip -6 route show dev veth98')
output = check_output('ip -6 route show dev veth98') output = check_output('ip -6 route show dev veth98')
@ -5196,42 +5148,31 @@ class NetworkdDHCP6PDTests(unittest.TestCase, Utilities):
output = check_output('ip -6 address show dev dummy97 scope global') output = check_output('ip -6 address show dev dummy97 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]06:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]06:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 route show dev dummy97') print('### ip -6 route show dev dummy97')
output = check_output('ip -6 route show dev dummy97') output = check_output('ip -6 route show dev dummy97')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]06::/64 proto kernel metric [0-9]* expires')
# Test case for reconfigure # Test case for reconfigure
check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env) check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
self.wait_online(['dummy98:routable']) self.wait_online(['dummy98:routable'])
print('### ip -6 address show dev dummy98 scope global') print('### ip -6 address show dev dummy98 scope global')
output = check_output('ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]03:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy99 scope global')
print(output)
# Assign=no
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03')
print('### ip -6 route show dev dummy98') print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev dummy99')
output = check_output('ip -6 route show dev dummy99')
print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires')
class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
links = [ links = [

View File

@ -4,7 +4,6 @@
set -eux set -eux
systemd-analyze log-level debug systemd-analyze log-level debug
export SYSTEMD_LOG_LEVEL=debug
mkdir -p /tmp/img/usr/lib/systemd/system/ mkdir -p /tmp/img/usr/lib/systemd/system/
mkdir -p /tmp/img/opt/ mkdir -p /tmp/img/opt/