1
0
mirror of https://github.com/systemd/systemd synced 2025-09-27 07:44:45 +02:00

Compare commits

..

No commits in common. "0cfb490fe9e3af39f7d7f9431b9fee9b5c98b992" and "31363bd564021e52a192d062f18459205cbf7685" have entirely different histories.

37 changed files with 1411 additions and 1955 deletions

4
NEWS
View File

@ -112,10 +112,6 @@ CHANGES WITH 246:
read and even write access to all these otherwise unmappable files, read and even write access to all these otherwise unmappable files,
which is quite likely a major security problem. which is quite likely a major security problem.
* tmpfs mounts automatically created by systemd (/tmp, /run, /dev/shm,
and others) now have a size and inode limits applied (50% of RAM for
/tmp, 10% of RAM for /dev/shm, etc.)
* nss-mymachines lost support for resolution of users and groups, and * nss-mymachines lost support for resolution of users and groups, and
now only does resolution of hostnames. This functionality is now now only does resolution of hostnames. This functionality is now
provided by nss-systemd. Thus, the 'mymachines' entry should be provided by nss-systemd. Thus, the 'mymachines' entry should be

View File

@ -809,6 +809,16 @@
<literal>false</literal>. See the [IPv6PrefixDelegation] and the [IPv6Prefix] sections for more <literal>false</literal>. See the [IPv6PrefixDelegation] and the [IPv6Prefix] sections for more
configuration options.</para></listitem> configuration options.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>IPv6PDSubnetId=</varname></term>
<listitem><para>Configure a specific subnet ID on the interface from a (previously) received prefix delegation.
You can either set "auto" (the default) or a specific subnet ID
(as defined in <ulink url="https://tools.ietf.org/html/rfc4291#section-2.5.4">RFC 4291</ulink>, section 2.5.4),
in which case the allowed value is hexadecimal, from 0 to 0x7fffffffffffffff inclusive.
This option is only effective when used together with <varname>IPv6PrefixDelegation=</varname>
and the corresponding configuration on the upstream interface.
</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>IPv6MTUBytes=</varname></term> <term><varname>IPv6MTUBytes=</varname></term>
<listitem><para>Configures IPv6 maximum transmission unit (MTU). <listitem><para>Configures IPv6 maximum transmission unit (MTU).
@ -1883,6 +1893,25 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>AssignAcquiredDelegatedPrefixAddress=</varname></term>
<listitem>
<para>Takes a boolean. Specifies whether to add an address from the delegated prefixes which are received
from the WAN interface by the <varname>IPv6PrefixDelegation=</varname>. When true (on LAN interfce), the EUI-64
algorithm will be used to form an interface identifier from the delegated prefixes. Defaults to true.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AssignAcquiredDelegatedPrefixToken=</varname></term>
<listitem>
<para>Specifies an optional address generation mode for <varname>AssignAcquiredDelegatedPrefixAddress=</varname>.
Takes an IPv6 address. When set, the lower bits of the supplied address are combined with the upper bits of a
delegatad prefix received from the WAN interface by the <varname>IPv6PrefixDelegation=</varname> prefixes to
form a complete address.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>PrefixDelegationHint=</varname></term> <term><varname>PrefixDelegationHint=</varname></term>
<listitem> <listitem>
@ -1937,48 +1966,6 @@
</variablelist> </variablelist>
</refsect1> </refsect1>
<refsect1>
<title>[DHCPv6PrefixDelegation] Section Options</title>
<para>The [DHCPv6PrefixDelegation] section configures delegated prefix assigned by DHCPv6 server.
The settings in this section are used only when <varname>IPv6PrefixDelegation=</varname> setting is
enabled, or set to <literal>dhcp6</literal>.</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>SubnetId=</varname></term>
<listitem>
<para>Configure a specific subnet ID on the interface from a (previously) received prefix
delegation. You can either set "auto" (the default) or a specific subnet ID (as defined in
<ulink url="https://tools.ietf.org/html/rfc4291#section-2.5.4">RFC 4291</ulink>, section
2.5.4), in which case the allowed value is hexadecimal, from 0 to 0x7fffffffffffffff
inclusive. This option is only effective when used together with
<varname>IPv6PrefixDelegation=</varname> and the corresponding configuration on the upstream
interface.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Assign=</varname></term>
<listitem>
<para>Takes a boolean. Specifies whether to add an address from the delegated prefixes which
are received from the WAN interface by the <varname>IPv6PrefixDelegation=</varname>. When
true (on LAN interfce), the EUI-64 algorithm will be used to form an interface identifier
from the delegated prefixes. Defaults to true.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Token=</varname></term>
<listitem>
<para>Specifies an optional address generation mode for <varname>Assign=</varname>. Takes an
IPv6 address. When set, the lower bits of the supplied address are combined with the upper
bits of a delegatad prefix received from the WAN interface by the
<varname>IPv6PrefixDelegation=</varname> prefixes to form a complete address.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1> <refsect1>
<title>[IPv6AcceptRA] Section Options</title> <title>[IPv6AcceptRA] Section Options</title>
<para>The [IPv6AcceptRA] section configures the IPv6 Router Advertisement (RA) client, if it is enabled <para>The [IPv6AcceptRA] section configures the IPv6 Router Advertisement (RA) client, if it is enabled

View File

@ -999,19 +999,16 @@ static int help(void) {
" --root-password=PASSWORD Set root password from plaintext password\n" " --root-password=PASSWORD Set root password from plaintext password\n"
" --root-password-file=FILE Set root password from file\n" " --root-password-file=FILE Set root password from file\n"
" --root-password-hashed=HASHED_PASSWORD Set root password from hashed password\n" " --root-password-hashed=HASHED_PASSWORD Set root password from hashed password\n"
" --root-shell=SHELL Set root shell\n"
" --prompt-locale Prompt the user for locale settings\n" " --prompt-locale Prompt the user for locale settings\n"
" --prompt-keymap Prompt the user for keymap settings\n" " --prompt-keymap Prompt the user for keymap settings\n"
" --prompt-timezone Prompt the user for timezone\n" " --prompt-timezone Prompt the user for timezone\n"
" --prompt-hostname Prompt the user for hostname\n" " --prompt-hostname Prompt the user for hostname\n"
" --prompt-root-password Prompt the user for root password\n" " --prompt-root-password Prompt the user for root password\n"
" --prompt-root-shell Prompt the user for root shell\n"
" --prompt Prompt for all of the above\n" " --prompt Prompt for all of the above\n"
" --copy-locale Copy locale from host\n" " --copy-locale Copy locale from host\n"
" --copy-keymap Copy keymap from host\n" " --copy-keymap Copy keymap from host\n"
" --copy-timezone Copy timezone from host\n" " --copy-timezone Copy timezone from host\n"
" --copy-root-password Copy root password from host\n" " --copy-root-password Copy root password from host\n"
" --copy-root-shell Copy root shell from host\n"
" --copy Copy locale, keymap, timezone, root password\n" " --copy Copy locale, keymap, timezone, root password\n"
" --setup-machine-id Generate a new random machine ID\n" " --setup-machine-id Generate a new random machine ID\n"
" --force Overwrite existing files\n" " --force Overwrite existing files\n"

View File

@ -291,7 +291,7 @@ static void test_rs(void) {
assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0); assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
time_now + 30 * USEC_PER_SEC, 0, time_now + 2 *USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); test_rs_hangcheck, NULL) >= 0);
assert_se(sd_ndisc_stop(nd) >= 0); assert_se(sd_ndisc_stop(nd) >= 0);
@ -393,7 +393,7 @@ static void test_timeout(void) {
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
time_now + 30 * USEC_PER_SEC, 0, time_now + 2U * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); test_rs_hangcheck, NULL) >= 0);
assert_se(sd_ndisc_start(nd) >= 0); assert_se(sd_ndisc_start(nd) >= 0);

View File

@ -125,17 +125,6 @@ void address_free(Address *address) {
if (address->link && !address->acd) { if (address->link && !address->acd) {
set_remove(address->link->addresses, address); set_remove(address->link->addresses, address);
set_remove(address->link->addresses_foreign, address); set_remove(address->link->addresses_foreign, address);
set_remove(address->link->static_addresses, address);
if (address->link->dhcp_address == address)
address->link->dhcp_address = NULL;
if (address->link->dhcp_address_old == address)
address->link->dhcp_address_old = NULL;
set_remove(address->link->dhcp6_addresses, address);
set_remove(address->link->dhcp6_addresses_old, address);
set_remove(address->link->dhcp6_pd_addresses, address);
set_remove(address->link->dhcp6_pd_addresses_old, address);
set_remove(address->link->ndisc_addresses, address);
set_remove(address->link->ndisc_addresses_old, address);
if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address)) if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr)); memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
@ -216,7 +205,7 @@ static int address_compare_func(const Address *a1, const Address *a2) {
} }
} }
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free); DEFINE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
bool address_equal(Address *a1, Address *a2) { bool address_equal(Address *a1, Address *a2) {
if (a1 == a2) if (a1 == a2)
@ -355,8 +344,11 @@ int address_update(
int r; int r;
assert(address); assert(address);
assert(address->link);
assert(cinfo); assert(cinfo);
assert_return(address->link, 1);
if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
ready = address_is_ready(address); ready = address_is_ready(address);
@ -364,28 +356,19 @@ int address_update(
address->scope = scope; address->scope = scope;
address->cinfo = *cinfo; address->cinfo = *cinfo;
if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
link_update_operstate(address->link, true); link_update_operstate(address->link, true);
link_check_ready(address->link); link_check_ready(address->link);
if (!ready && address_is_ready(address)) { if (!ready &&
if (address->callback) { address_is_ready(address) &&
r = address->callback(address); address->family == AF_INET6 &&
if (r < 0)
return r;
}
if (address->family == AF_INET6 &&
in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 && in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
IN6_IS_ADDR_UNSPECIFIED(&address->link->ipv6ll_address) > 0) { in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
r = link_ipv6ll_gained(address->link, &address->in_addr.in6); r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
if (r < 0) if (r < 0)
return r; return r;
} }
}
return 0; return 0;
} }
@ -603,11 +586,9 @@ int address_configure(
Address *address, Address *address,
Link *link, Link *link,
link_netlink_message_handler_t callback, link_netlink_message_handler_t callback,
bool update, bool update) {
Address **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
Address *a;
int r; int r;
assert(address); assert(address);
@ -628,13 +609,6 @@ int address_configure(
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m"); return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
if (DEBUG_LOGGING) {
_cleanup_free_ char *str = NULL;
(void) in_addr_to_string(address->family, &address->in_addr, &str);
log_link_debug(link, "%s address: %s", update ? "Updating" : "Configuring", strna(str));
}
if (update) if (update)
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
link->ifindex, address->family); link->ifindex, address->family);
@ -716,9 +690,9 @@ int address_configure(
link_ref(link); link_ref(link);
if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer)) if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a); r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL);
else else
r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a); r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
if (r < 0) { if (r < 0) {
address_release(address); address_release(address);
return log_link_error_errno(link, r, "Could not add address: %m"); return log_link_error_errno(link, r, "Could not add address: %m");
@ -738,9 +712,6 @@ int address_configure(
log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m"); log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
} }
if (ret)
*ret = a;
return 1; return 1;
} }

View File

@ -20,7 +20,6 @@ typedef struct Address Address;
typedef struct Network Network; typedef struct Network Network;
typedef struct Link Link; typedef struct Link Link;
typedef struct NetworkConfigSection NetworkConfigSection; typedef struct NetworkConfigSection NetworkConfigSection;
typedef int (*address_ready_callback_t)(Address *address);
struct Address { struct Address {
Network *network; Network *network;
@ -48,9 +47,6 @@ struct Address {
bool autojoin:1; bool autojoin:1;
AddressFamily duplicate_address_detection; AddressFamily duplicate_address_detection;
/* Called when address become ready */
address_ready_callback_t callback;
sd_ipv4acd *acd; sd_ipv4acd *acd;
LIST_FIELDS(Address, addresses); LIST_FIELDS(Address, addresses);
@ -64,7 +60,7 @@ int address_get(Link *link, int family, const union in_addr_union *in_addr, unsi
bool address_exists(Link *link, int family, const union in_addr_union *in_addr); bool address_exists(Link *link, int family, const union in_addr_union *in_addr);
int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo); int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo);
int address_drop(Address *address); int address_drop(Address *address);
int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret); int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update);
int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback); int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback);
bool address_equal(Address *a1, Address *a2); bool address_equal(Address *a1, Address *a2);
bool address_is_ready(const Address *a); bool address_is_ready(const Address *a);

View File

@ -20,58 +20,38 @@
#include "sysctl-util.h" #include "sysctl-util.h"
#include "web-util.h" #include "web-util.h"
static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback);
static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback);
static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback);
static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, link_netlink_message_handler_t callback);
static int dhcp4_update_address(Link *link, bool announce); static int dhcp4_update_address(Link *link, bool announce);
static int dhcp4_remove_all(Link *link); static int dhcp4_remove_all(Link *link);
static int dhcp4_release_old_lease(Link *link, bool force);
static int dhcp4_address_callback(Address *address) { static void dhcp4_release_old_lease(Link *link) {
assert(address); struct in_addr address = {}, address_old = {};
assert(address->link);
/* Do not call this callback again. */
address->callback = NULL;
return dhcp4_release_old_lease(address->link, true);
}
static int dhcp4_release_old_lease(Link *link, bool force) {
Route *route;
Iterator i;
int k, r = 0;
assert(link); assert(link);
if (!link->dhcp_address_old && set_isempty(link->dhcp_routes_old)) if (!link->dhcp_lease_old)
return 0; return;
if (!force && (link->dhcp_address && !address_is_ready(link->dhcp_address))) { assert(link->dhcp_lease);
log_link_debug(link, "New DHCPv4 address is not ready. The old lease will be removed later.");
link->dhcp_address->callback = dhcp4_address_callback;
return 0;
}
log_link_debug(link, "Removing old DHCPv4 address and routes."); (void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old);
(void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
(void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false, NULL);
(void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false, NULL);
(void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false, NULL);
if (!in4_addr_equal(&address_old, &address))
(void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old, NULL);
link->dhcp_lease_old = sd_dhcp_lease_unref(link->dhcp_lease_old);
link_dirty(link); link_dirty(link);
SET_FOREACH(route, link->dhcp_routes_old, i) {
k = route_remove(route, link, NULL);
if (k < 0)
r = k;
}
if (link->dhcp_address_old) {
k = address_remove(link->dhcp_address_old, link, NULL);
if (k < 0)
r = k;
}
return r;
} }
static void dhcp4_check_ready(Link *link) { static void dhcp4_check_ready(Link *link) {
int r;
if (link->network->dhcp_send_decline && !link->dhcp4_address_bind) if (link->network->dhcp_send_decline && !link->dhcp4_address_bind)
return; return;
@ -79,14 +59,8 @@ static void dhcp4_check_ready(Link *link) {
return; return;
link->dhcp4_configured = true; link->dhcp4_configured = true;
/* New address and routes are configured now. Let's release old lease. */ /* New address and routes are configured now. Let's release old lease. */
r = dhcp4_release_old_lease(link, false); dhcp4_release_old_lease(link);
if (r < 0) {
link_enter_failed(link);
return;
}
link_check_ready(link); link_check_ready(link);
} }
@ -150,25 +124,27 @@ static bool link_prefixroute(Link *link) {
link->manager->dhcp4_prefix_root_cannot_set_table; link->manager->dhcp4_prefix_root_cannot_set_table;
} }
static int dhcp_route_configure(Route *route, Link *link) { static int dhcp_route_configure(Route **route, Link *link) {
Route *ret;
int r; int r;
assert(route); assert(route);
assert(*route);
assert(link); assert(link);
r = route_configure(route, link, dhcp4_route_handler, &ret); if (set_contains(link->dhcp_routes, *route))
if (r < 0) return 0;
return log_link_error_errno(link, r, "Failed to set DHCPv4 route: %m");
r = route_configure(*route, link, dhcp4_route_handler);
if (r <= 0)
return r;
link->dhcp4_messages++; link->dhcp4_messages++;
r = set_ensure_put(&link->dhcp_routes, &route_hash_ops, ret); r = set_put(link->dhcp_routes, *route);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv4 route: %m"); return r;
(void) set_remove(link->dhcp_routes_old, ret);
TAKE_PTR(*route);
return 0; return 0;
} }
@ -211,7 +187,7 @@ static int link_set_dns_routes(Link *link, const struct in_addr *address) {
route->priority = link->network->dhcp_route_metric; route->priority = link->network->dhcp_route_metric;
route->table = table; route->table = table;
r = dhcp_route_configure(route, link); r = dhcp_route_configure(&route, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set route to DNS server: %m"); return log_link_error_errno(link, r, "Could not set route to DNS server: %m");
} }
@ -255,7 +231,6 @@ static int link_set_dhcp_routes(Link *link) {
struct in_addr address; struct in_addr address;
int r, n, i; int r, n, i;
uint32_t table; uint32_t table;
Route *rt;
assert(link); assert(link);
@ -270,11 +245,12 @@ static int link_set_dhcp_routes(Link *link) {
* the addresses now, let's not configure the routes either. */ * the addresses now, let's not configure the routes either. */
return 0; return 0;
while ((rt = set_steal_first(link->dhcp_routes))) { r = set_ensure_allocated(&link->dhcp_routes, &route_hash_ops);
r = set_ensure_put(&link->dhcp_routes_old, &route_hash_ops, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m"); return log_oom();
}
/* Clear old entries in case the set was already allocated */
set_clear(link->dhcp_routes);
table = link_get_dhcp_route_table(link); table = link_get_dhcp_route_table(link);
@ -289,7 +265,7 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create prefix route: %m"); return log_link_error_errno(link, r, "Could not create prefix route: %m");
r = dhcp_route_configure(prefix_route, link); r = dhcp_route_configure(&prefix_route, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set prefix route: %m"); return log_link_error_errno(link, r, "Could not set prefix route: %m");
} }
@ -340,7 +316,7 @@ static int link_set_dhcp_routes(Link *link) {
if (set_contains(link->dhcp_routes, route)) if (set_contains(link->dhcp_routes, route))
continue; continue;
r = dhcp_route_configure(route, link); r = dhcp_route_configure(&route, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set route: %m"); return log_link_error_errno(link, r, "Could not set route: %m");
} }
@ -380,7 +356,7 @@ static int link_set_dhcp_routes(Link *link) {
route_gw->table = table; route_gw->table = table;
route_gw->mtu = link->network->dhcp_route_mtu; route_gw->mtu = link->network->dhcp_route_mtu;
r = dhcp_route_configure(route_gw, link); r = dhcp_route_configure(&route_gw, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set host route: %m"); return log_link_error_errno(link, r, "Could not set host route: %m");
@ -396,11 +372,12 @@ static int link_set_dhcp_routes(Link *link) {
route->table = table; route->table = table;
route->mtu = link->network->dhcp_route_mtu; route->mtu = link->network->dhcp_route_mtu;
r = dhcp_route_configure(route, link); r = dhcp_route_configure(&route, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set router: %m"); return log_link_error_errno(link, r, "Could not set router: %m");
} }
Route *rt;
LIST_FOREACH(routes, rt, link->network->static_routes) { LIST_FOREACH(routes, rt, link->network->static_routes) {
if (!rt->gateway_from_dhcp) if (!rt->gateway_from_dhcp)
continue; continue;
@ -410,15 +387,272 @@ static int link_set_dhcp_routes(Link *link) {
rt->gw.in = router[0]; rt->gw.in = router[0];
r = dhcp_route_configure(rt, link); r = route_configure(rt, link, dhcp4_route_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set gateway: %m"); return log_link_error_errno(link, r, "Could not set gateway: %m");
if (r > 0)
link->dhcp4_messages++;
} }
} }
return link_set_dns_routes(link, &address); return link_set_dns_routes(link, &address);
} }
static int dhcp_route_remove(Route *route, Link *link, link_netlink_message_handler_t callback) {
int r;
r = route_remove(route, link, callback);
if (r < 0)
return r;
if (callback)
link->dhcp4_remove_messages++;
return 0;
}
static int dhcp_remove_routes(
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
_cleanup_free_ sd_dhcp_route **routes = NULL;
uint32_t table;
int n, i, r;
assert(link);
assert(address);
if (!link->network->dhcp_use_routes)
return 0;
n = sd_dhcp_lease_get_routes(lease, &routes);
if (IN_SET(n, 0, -ENODATA))
return 0;
else if (n < 0)
return log_link_error_errno(link, n, "DHCP error: Failed to get routes: %m");
table = link_get_dhcp_route_table(link);
for (i = 0; i < n; i++) {
_cleanup_(route_freep) Route *route = NULL;
r = route_new(&route);
if (r < 0)
return log_oom();
route->family = AF_INET;
assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
route->priority = link->network->dhcp_route_metric;
route->table = table;
route->scope = route_scope_from_address(route, address);
if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
route->prefsrc.in = *address;
if (!remove_all && set_contains(link->dhcp_routes, route))
continue;
r = dhcp_route_remove(route, link, callback);
if (r < 0)
return r;
}
return n;
}
static int dhcp_remove_router(
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
_cleanup_(route_freep) Route *route_gw = NULL, *route = NULL;
const struct in_addr *router;
uint32_t table;
int r;
assert(link);
assert(address);
if (!link->network->dhcp_use_gateway)
return 0;
r = sd_dhcp_lease_get_router(lease, &router);
if (IN_SET(r, 0, -ENODATA)) {
log_link_debug(link, "DHCP: No gateway received from DHCP server.");
return 0;
} else if (r < 0)
return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
else if (in4_addr_is_null(&router[0])) {
log_link_info(link, "DHCP: Received gateway is null, ignoring.");
return 0;
}
table = link_get_dhcp_route_table(link);
r = route_new(&route_gw);
if (r < 0)
return log_oom();
route_gw->family = AF_INET;
route_gw->dst.in = router[0];
route_gw->dst_prefixlen = 32;
route_gw->prefsrc.in = *address;
route_gw->scope = RT_SCOPE_LINK;
route_gw->protocol = RTPROT_DHCP;
route_gw->priority = link->network->dhcp_route_metric;
route_gw->table = table;
if (remove_all || !set_contains(link->dhcp_routes, route_gw)) {
r = dhcp_route_remove(route_gw, link, callback);
if (r < 0)
return r;
}
r = route_new(&route);
if (r < 0)
return log_oom();
route->family = AF_INET;
route->gw.in = router[0];
route->prefsrc.in = *address;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = table;
if (remove_all || !set_contains(link->dhcp_routes, route)) {
r = dhcp_route_remove(route, link, callback);
if (r < 0)
return r;
}
Route *rt;
LIST_FOREACH(routes, rt, link->network->static_routes) {
if (!rt->gateway_from_dhcp)
continue;
if (rt->family != AF_INET)
continue;
if (!remove_all && in4_addr_equal(router, &rt->gw.in))
continue;
r = dhcp_route_remove(rt, link, callback);
if (r < 0)
return r;
}
return 0;
}
static int dhcp_remove_dns_routes(
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
const struct in_addr *dns;
uint32_t table;
int i, n, r;
assert(link);
assert(lease);
assert(link->network);
if (!link->network->dhcp_use_dns ||
!link->network->dhcp_routes_to_dns)
return 0;
n = sd_dhcp_lease_get_dns(lease, &dns);
if (IN_SET(n, 0, -ENODATA))
return 0;
if (n < 0)
return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
table = link_get_dhcp_route_table(link);
for (i = 0; i < n; i ++) {
_cleanup_(route_freep) Route *route = NULL;
r = route_new(&route);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
route->family = AF_INET;
route->dst.in = dns[i];
route->dst_prefixlen = 32;
route->prefsrc.in = *address;
route->scope = RT_SCOPE_LINK;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = table;
if (!remove_all && set_contains(link->dhcp_routes, route))
continue;
r = dhcp_route_remove(route, link, callback);
if (r < 0)
return r;
}
if (!link_prefixroute(link)) {
_cleanup_(route_freep) Route *prefix_route = NULL;
r = dhcp_prefix_route_from_lease(lease, table, address, &prefix_route);
if (r < 0)
return log_link_warning_errno(link, r, "Could not create prefix route: %m");
if (remove_all || !set_contains(link->dhcp_routes, prefix_route)) {
r = dhcp_route_remove(prefix_route, link, callback);
if (r < 0)
return r;
}
}
return 0;
}
static int dhcp_remove_address(
Link *link, sd_dhcp_lease *lease,
const struct in_addr *address,
link_netlink_message_handler_t callback) {
_cleanup_(address_freep) Address *a = NULL;
struct in_addr netmask;
int r;
assert(link);
assert(address);
if (in4_addr_is_null(address))
return 0;
r = address_new(&a);
if (r < 0)
return log_oom();
a->family = AF_INET;
a->in_addr.in = *address;
if (sd_dhcp_lease_get_netmask(lease, &netmask) >= 0)
a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
r = address_remove(a, link, callback);
if (r < 0)
return r;
if (callback)
link->dhcp4_remove_messages++;
return 0;
}
static int dhcp_reset_mtu(Link *link) { static int dhcp_reset_mtu(Link *link) {
uint16_t mtu; uint16_t mtu;
int r; int r;
@ -522,33 +756,37 @@ static int dhcp4_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
} }
static int dhcp4_remove_all(Link *link) { static int dhcp4_remove_all(Link *link) {
Route *route; struct in_addr address;
Iterator i; int r;
int k, r = 0;
assert(link); assert(link);
assert(link->dhcp_lease);
SET_FOREACH(route, link->dhcp_routes, i) { r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
k = route_remove(route, link, dhcp4_remove_route_handler); if (r < 0)
if (k < 0) return log_link_error_errno(link, r, "Failed to get DHCPv4 address: %m");
r = k;
else
link->dhcp4_remove_messages++;
}
if (link->dhcp_address) {
k = address_remove(link->dhcp_address, link, dhcp4_remove_address_handler);
if (k < 0)
r = k;
else
link->dhcp4_remove_messages++;
}
r = dhcp_remove_routes(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r; return r;
r = dhcp_remove_router(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r;
r = dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r;
r = dhcp_remove_address(link, link->dhcp_lease, &address, dhcp4_remove_address_handler);
if (r < 0)
return r;
return 0;
} }
static int dhcp_lease_lost(Link *link) { static int dhcp_lease_lost(Link *link) {
int k, r; int r;
assert(link); assert(link);
assert(link->dhcp_lease); assert(link->dhcp_lease);
@ -558,26 +796,24 @@ static int dhcp_lease_lost(Link *link) {
link->dhcp4_configured = false; link->dhcp4_configured = false;
/* dhcp_lease_lost() may be called during renewing IP address. */ /* dhcp_lease_lost() may be called during renewing IP address. */
k = dhcp4_release_old_lease(link, true); dhcp4_release_old_lease(link);
if (k < 0)
r = k;
k = dhcp4_remove_all(link); r = dhcp4_remove_all(link);
if (k < 0) if (r < 0)
r = k; return r;
k = dhcp_reset_mtu(link); r = dhcp_reset_mtu(link);
if (k < 0) if (r < 0)
r = k; return r;
k = dhcp_reset_hostname(link); r = dhcp_reset_hostname(link);
if (k < 0) if (r < 0)
r = k; return r;
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link_dirty(link); link_dirty(link);
return r; return 0;
} }
static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
@ -739,7 +975,6 @@ static int dhcp4_update_address(Link *link, bool announce) {
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
struct in_addr address, netmask; struct in_addr address, netmask;
unsigned prefixlen; unsigned prefixlen;
Address *ret;
int r; int r;
assert(link); assert(link);
@ -814,13 +1049,9 @@ static int dhcp4_update_address(Link *link, bool announce) {
/* allow reusing an existing address and simply update its lifetime /* allow reusing an existing address and simply update its lifetime
* in case it already exists */ * in case it already exists */
r = address_configure(addr, link, dhcp4_address_handler, true, &ret); r = address_configure(addr, link, dhcp4_address_handler, true);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv4 address: %m"); return r;
if (!address_equal(link->dhcp_address, ret))
link->dhcp_address_old = link->dhcp_address;
link->dhcp_address = ret;
return 0; return 0;
} }
@ -920,11 +1151,32 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) { static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {
int r; int r;
r = dhcp_lease_acquired(client, link); link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
if (r < 0)
(void) dhcp_lease_lost(link);
/* On IP address change, to keep the connectability, we would like to assign new address and
* routes, and then release old lease. There are two possible success paths:
*
* 1. new address and routes are configured.
* -> handled by dhcp_release_old_lease() in dhcp4_route_handler().
* 2. new address is configured and no route is requested.
* -> handled by dhcp_release_old_lease() in dhcp4_address_handler().
*
* On error in assigning new address and routes, then the link always enters to the failed
* state. And link_enter_failed() leads to the DHCP client to be stopped. So,
* dhcp_release_old_lease() will be also called by link_stop_clients().
*/
r = dhcp_lease_acquired(client, link);
if (r < 0) {
/* If it fails, then the new address is not configured yet.
* So, let's simply drop the old lease. */
sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp_lease = TAKE_PTR(link->dhcp_lease_old);
(void) dhcp_lease_lost(link);
return r; return r;
}
return 0;
} }
static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) { static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {

File diff suppressed because it is too large Load Diff

View File

@ -17,26 +17,17 @@ typedef enum DHCP6ClientStartMode {
typedef struct Link Link; typedef struct Link Link;
typedef struct Manager Manager; typedef struct Manager Manager;
typedef struct DHCP6DelegatedPrefix { bool dhcp6_get_prefix_delegation(Link *link);
struct in6_addr prefix; /* Prefix assigned to the link */ int dhcp6_request_prefix_delegation(Link *link);
struct in6_addr pd_prefix; /* PD prefix provided by DHCP6 lease */
Link *link;
} DHCP6DelegatedPrefix;
DHCP6DelegatedPrefix *dhcp6_pd_free(DHCP6DelegatedPrefix *p);
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free);
bool link_dhcp6_pd_is_enabled(Link *link);
int dhcp6_pd_remove(Link *link);
int dhcp6_configure(Link *link); int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link, int ir); int dhcp6_request_address(Link *link, int ir);
int dhcp6_request_prefix_delegation(Link *link); int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_delegated_prefix_token);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_subnet_id);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_token);
const char* dhcp6_client_start_mode_to_string(DHCP6ClientStartMode i) _const_; const char* dhcp6_client_start_mode_to_string(DHCP6ClientStartMode i) _const_;
DHCP6ClientStartMode dhcp6_client_start_mode_from_string(const char *s) _pure_; DHCP6ClientStartMode dhcp6_client_start_mode_from_string(const char *s) _pure_;

View File

@ -17,7 +17,7 @@ static int ipv4ll_address_lost(Link *link) {
assert(link); assert(link);
link->ipv4ll_address_configured = false; link->ipv4ll_address = false;
r = sd_ipv4ll_get_address(link->ipv4ll, &addr); r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
if (r < 0) if (r < 0)
@ -47,7 +47,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
int r; int r;
assert(link); assert(link);
assert(!link->ipv4ll_address_configured); assert(!link->ipv4ll_address);
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
@ -57,7 +57,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
} else if (r >= 0) } else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager); (void) manager_rtnl_process_address(rtnl, m, link->manager);
link->ipv4ll_address_configured = true; link->ipv4ll_address = true;
link_check_ready(link); link_check_ready(link);
return 1; return 1;
@ -71,7 +71,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
assert(ll); assert(ll);
assert(link); assert(link);
link->ipv4ll_address_configured = false; link->ipv4ll_address = false;
r = sd_ipv4ll_get_address(ll, &address); r = sd_ipv4ll_get_address(ll, &address);
if (r == -ENOENT) if (r == -ENOENT)
@ -92,7 +92,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen); ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
ll_addr->scope = RT_SCOPE_LINK; ll_addr->scope = RT_SCOPE_LINK;
r = address_configure(ll_addr, link, ipv4ll_address_handler, false, NULL); r = address_configure(ll_addr, link, ipv4ll_address_handler, false);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -691,6 +691,7 @@ static void link_free_engines(Link *link) {
link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server); link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server);
link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client); link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client);
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp_routes = set_free(link->dhcp_routes);
link->lldp = sd_lldp_unref(link->lldp); link->lldp = sd_lldp_unref(link->lldp);
@ -698,7 +699,6 @@ static void link_free_engines(Link *link) {
link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll); link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll);
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease);
link->ndisc = sd_ndisc_unref(link->ndisc); link->ndisc = sd_ndisc_unref(link->ndisc);
link->radv = sd_radv_unref(link->radv); link->radv = sd_radv_unref(link->radv);
} }
@ -711,32 +711,17 @@ static Link *link_free(Link *link) {
link_ntp_settings_clear(link); link_ntp_settings_clear(link);
link_dns_settings_clear(link); link_dns_settings_clear(link);
link->routes = set_free(link->routes); link->routes = set_free_with_destructor(link->routes, route_free);
link->routes_foreign = set_free(link->routes_foreign); link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
link->dhcp_routes = set_free(link->dhcp_routes);
link->dhcp_routes_old = set_free(link->dhcp_routes_old);
link->dhcp6_routes = set_free(link->dhcp6_routes);
link->dhcp6_routes_old = set_free(link->dhcp6_routes_old);
link->dhcp6_pd_routes = set_free(link->dhcp6_pd_routes);
link->dhcp6_pd_routes_old = set_free(link->dhcp6_pd_routes_old);
link->ndisc_routes = set_free(link->ndisc_routes);
link->ndisc_routes_old = set_free(link->ndisc_routes_old);
link->nexthops = set_free(link->nexthops); link->nexthops = set_free_with_destructor(link->nexthops, nexthop_free);
link->nexthops_foreign = set_free(link->nexthops_foreign); link->nexthops_foreign = set_free_with_destructor(link->nexthops_foreign, nexthop_free);
link->neighbors = set_free(link->neighbors); link->neighbors = set_free_with_destructor(link->neighbors, neighbor_free);
link->neighbors_foreign = set_free(link->neighbors_foreign); link->neighbors_foreign = set_free_with_destructor(link->neighbors_foreign, neighbor_free);
link->addresses = set_free(link->addresses); link->addresses = set_free_with_destructor(link->addresses, address_free);
link->addresses_foreign = set_free(link->addresses_foreign); link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
link->static_addresses = set_free(link->static_addresses);
link->dhcp6_addresses = set_free(link->dhcp6_addresses);
link->dhcp6_addresses_old = set_free(link->dhcp6_addresses_old);
link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses);
link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old);
link->ndisc_addresses = set_free(link->ndisc_addresses);
link->ndisc_addresses_old = set_free(link->ndisc_addresses_old);
while ((address = link->pool_addresses)) { while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address); LIST_REMOVE(addresses, link->pool_addresses, address);
@ -849,12 +834,6 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m"); r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
} }
if (link_dhcp6_pd_is_enabled(link)) {
k = dhcp6_pd_remove(link);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
}
if (link->ndisc) { if (link->ndisc) {
k = sd_ndisc_stop(link->ndisc); k = sd_ndisc_stop(link->ndisc);
if (k < 0) if (k < 0)
@ -1058,13 +1037,12 @@ int link_request_set_routes(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
assert(link->addresses_configured);
assert(link->address_messages == 0);
assert(link->state != _LINK_STATE_INVALID); assert(link->state != _LINK_STATE_INVALID);
link->static_routes_configured = false; link->static_routes_configured = false;
if (!link->addresses_ready)
return 0;
if (!link_has_carrier(link) && !link->network->configure_without_carrier) if (!link_has_carrier(link) && !link->network->configure_without_carrier)
/* During configuring addresses, the link lost its carrier. As networkd is dropping /* During configuring addresses, the link lost its carrier. As networkd is dropping
* the addresses now, let's not configure the routes either. */ * the addresses now, let's not configure the routes either. */
@ -1083,7 +1061,7 @@ int link_request_set_routes(Link *link) {
if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY)) if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
continue; continue;
r = route_configure(rt, link, route_handler, NULL); r = route_configure(rt, link, route_handler);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not set routes: %m"); return log_link_warning_errno(link, r, "Could not set routes: %m");
if (r > 0) if (r > 0)
@ -1104,14 +1082,12 @@ int link_request_set_routes(Link *link) {
void link_check_ready(Link *link) { void link_check_ready(Link *link) {
Address *a; Address *a;
Iterator i; Iterator i;
int r;
assert(link); assert(link);
if (link->state == LINK_STATE_CONFIGURED) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
return; log_link_debug(link, "%s(): link is in failed or linger state.", __func__);
if (link->state != LINK_STATE_CONFIGURING) {
log_link_debug(link, "%s(): link is in %s state.", __func__, link_state_to_string(link->state));
return; return;
} }
@ -1137,6 +1113,15 @@ void link_check_ready(Link *link) {
return; return;
} }
if (!link->addresses_ready) {
link->addresses_ready = true;
r = link_request_set_routes(link);
if (r < 0)
link_enter_failed(link);
log_link_debug(link, "%s(): static addresses are configured. Configuring static routes.", __func__);
return;
}
if (!link->static_routes_configured) { if (!link->static_routes_configured) {
log_link_debug(link, "%s(): static routes are not configured.", __func__); log_link_debug(link, "%s(): static routes are not configured.", __func__);
return; return;
@ -1164,7 +1149,7 @@ void link_check_ready(Link *link) {
if (link_has_carrier(link) || !link->network->configure_without_carrier) { if (link_has_carrier(link) || !link->network->configure_without_carrier) {
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) { if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address) {
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__); log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
return; return;
} }
@ -1175,19 +1160,17 @@ void link_check_ready(Link *link) {
return; return;
} }
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && set_isempty(link->addresses)) {
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) && log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no address is assigned yet.", __func__);
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__);
return; return;
} }
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) || link_ipv6_accept_ra_enabled(link)) { if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || dhcp6_get_prefix_delegation(link) || link_ipv6_accept_ra_enabled(link)) {
if (!link->dhcp4_configured && if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) && !(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) && !(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
!(link->ndisc_addresses_configured && link->ndisc_routes_configured) && !(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) { !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address)) {
/* When DHCP or RA is enabled, at least one protocol must provide an address, or /* When DHCP or RA is enabled, at least one protocol must provide an address, or
* an IPv4ll fallback address must be configured. */ * an IPv4ll fallback address must be configured. */
log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__); log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
@ -1206,6 +1189,7 @@ void link_check_ready(Link *link) {
} }
} }
if (link->state != LINK_STATE_CONFIGURED)
link_enter_configured(link); link_enter_configured(link);
return; return;
@ -1238,50 +1222,6 @@ static int link_request_set_neighbors(Link *link) {
return 0; return 0;
} }
static int link_set_bridge_fdb(Link *link) {
FdbEntry *fdb_entry;
int r;
LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
r = fdb_entry_configure(link, fdb_entry);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
}
return 0;
}
static int static_address_ready_callback(Address *address) {
Address *a;
Iterator i;
Link *link;
assert(address);
assert(address->link);
link = address->link;
if (!link->addresses_configured)
return 0;
SET_FOREACH(a, link->static_addresses, i)
if (!address_is_ready(a)) {
_cleanup_free_ char *str = NULL;
(void) in_addr_to_string(a->family, &a->in_addr, &str);
log_link_debug(link, "an address %s/%u is not ready", strnull(str), a->prefixlen);
return 0;
}
/* This should not be called again */
SET_FOREACH(a, link->static_addresses, i)
a->callback = NULL;
link->addresses_ready = true;
return link_request_set_routes(link);
}
static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
@ -1307,50 +1247,23 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
(void) manager_rtnl_process_address(rtnl, m, link->manager); (void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->address_messages == 0) { if (link->address_messages == 0) {
Address *a;
log_link_debug(link, "Addresses set"); log_link_debug(link, "Addresses set");
link->addresses_configured = true; link->addresses_configured = true;
link_check_ready(link);
/* When all static addresses are already ready, then static_address_ready_callback()
* will not be called automatically. So, call it here. */
a = set_first(link->static_addresses);
if (!a) {
log_link_warning(link, "No static address is stored.");
link_enter_failed(link);
return 1;
}
if (!a->callback) {
log_link_warning(link, "Address ready callback is not set.");
link_enter_failed(link);
return 1;
}
r = a->callback(a);
if (r < 0)
link_enter_failed(link);
} }
return 1; return 1;
} }
static int static_address_configure(Address *address, Link *link, bool update) { static int link_set_bridge_fdb(Link *link) {
Address *ret; FdbEntry *fdb_entry;
int r; int r;
assert(address); LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
assert(link); r = fdb_entry_configure(link, fdb_entry);
r = address_configure(address, link, address_handler, update, &ret);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not configure static address: %m"); return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
}
link->address_messages++;
r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to store static address: %m");
ret->callback = static_address_ready_callback;
return 0; return 0;
} }
@ -1389,12 +1302,16 @@ static int link_request_set_addresses(Link *link) {
else else
update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0; update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0;
r = static_address_configure(ad, link, update); r = address_configure(ad, link, address_handler, update);
if (r < 0) if (r < 0)
return r; return log_link_warning_errno(link, r, "Could not set addresses: %m");
if (r > 0)
link->address_messages++;
} }
if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) if (IN_SET(link->network->router_prefix_delegation,
RADV_PREFIX_DELEGATION_STATIC,
RADV_PREFIX_DELEGATION_BOTH))
LIST_FOREACH(prefixes, p, link->network->static_prefixes) { LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *address = NULL;
@ -1403,20 +1320,22 @@ static int link_request_set_addresses(Link *link) {
r = address_new(&address); r = address_new(&address);
if (r < 0) if (r < 0)
return log_oom(); return log_link_error_errno(link, r, "Could not allocate address: %m");
r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen); r = sd_radv_prefix_get_prefix(p->radv_prefix, &address->in_addr.in6, &address->prefixlen);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not get RA prefix: %m"); return r;
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m"); return r;
address->family = AF_INET6; address->family = AF_INET6;
r = static_address_configure(address, link, true); r = address_configure(address, link, address_handler, true);
if (r < 0) if (r < 0)
return r; return log_link_warning_errno(link, r, "Could not set addresses: %m");
if (r > 0)
link->address_messages++;
} }
LIST_FOREACH(labels, label, link->network->address_labels) { LIST_FOREACH(labels, label, link->network->address_labels) {
@ -1427,7 +1346,8 @@ static int link_request_set_addresses(Link *link) {
link->address_label_messages++; link->address_label_messages++;
} }
/* now that we can figure out a default address for the dhcp server, start it */ /* now that we can figure out a default address for the dhcp server,
start it */
if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) {
r = dhcp4_server_configure(link); r = dhcp4_server_configure(link);
if (r < 0) if (r < 0)
@ -1437,10 +1357,7 @@ static int link_request_set_addresses(Link *link) {
if (link->address_messages == 0) { if (link->address_messages == 0) {
link->addresses_configured = true; link->addresses_configured = true;
link->addresses_ready = true; link_check_ready(link);
r = link_request_set_routes(link);
if (r < 0)
return r;
} else { } else {
log_link_debug(link, "Setting addresses"); log_link_debug(link, "Setting addresses");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
@ -1700,9 +1617,7 @@ static int link_acquire_ipv6_conf(Link *link) {
log_link_debug(link, "Acquiring DHCPv6 lease"); log_link_debug(link, "Acquiring DHCPv6 lease");
} }
r = dhcp6_request_prefix_delegation(link); (void) dhcp6_request_prefix_delegation(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to request DHCPv6 prefix delegation: %m");
return 0; return 0;
} }
@ -4320,6 +4235,7 @@ int link_save(Link *link) {
if (link->network) { if (link->network) {
char **dhcp6_domains = NULL, **dhcp_domains = NULL; char **dhcp6_domains = NULL, **dhcp_domains = NULL;
const char *dhcp_domainname = NULL, *p; const char *dhcp_domainname = NULL, *p;
sd_dhcp6_lease *dhcp6_lease = NULL;
bool space; bool space;
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n", fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
@ -4331,6 +4247,12 @@ int link_save(Link *link) {
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "", st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? ":" : "",
st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : ""); st.max != LINK_OPERSTATE_RANGE_DEFAULT.max ? strempty(link_operstate_to_string(st.max)) : "");
if (link->dhcp6_client) {
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
if (r < 0 && r != -ENOMSG)
log_link_debug_errno(link, r, "Failed to get DHCPv6 lease: %m");
}
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
/************************************************************/ /************************************************************/
@ -4347,7 +4269,7 @@ int link_save(Link *link) {
link->dhcp_lease, link->dhcp_lease,
link->network->dhcp_use_dns, link->network->dhcp_use_dns,
SD_DHCP_LEASE_DNS, SD_DHCP_LEASE_DNS,
link->dhcp6_lease, dhcp6_lease,
link->network->dhcp6_use_dns, link->network->dhcp6_use_dns,
sd_dhcp6_lease_get_dns, sd_dhcp6_lease_get_dns,
NULL); NULL);
@ -4371,7 +4293,7 @@ int link_save(Link *link) {
link->dhcp_lease, link->dhcp_lease,
link->network->dhcp_use_ntp, link->network->dhcp_use_ntp,
SD_DHCP_LEASE_NTP, SD_DHCP_LEASE_NTP,
link->dhcp6_lease, dhcp6_lease,
link->network->dhcp6_use_ntp, link->network->dhcp6_use_ntp,
sd_dhcp6_lease_get_ntp_addrs, sd_dhcp6_lease_get_ntp_addrs,
sd_dhcp6_lease_get_ntp_fqdn); sd_dhcp6_lease_get_ntp_fqdn);
@ -4390,8 +4312,8 @@ int link_save(Link *link) {
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname); (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
(void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains); (void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains);
} }
if (link->dhcp6_lease) if (dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains); (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
} }
fputs("DOMAINS=", f); fputs("DOMAINS=", f);

View File

@ -87,7 +87,6 @@ typedef struct Link {
Set *addresses; Set *addresses;
Set *addresses_foreign; Set *addresses_foreign;
Set *static_addresses;
Set *neighbors; Set *neighbors;
Set *neighbors_foreign; Set *neighbors_foreign;
Set *routes; Set *routes;
@ -96,20 +95,32 @@ typedef struct Link {
Set *nexthops_foreign; Set *nexthops_foreign;
sd_dhcp_client *dhcp_client; sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease; sd_dhcp_lease *dhcp_lease, *dhcp_lease_old;
Address *dhcp_address, *dhcp_address_old; Set *dhcp_routes;
Set *dhcp_routes, *dhcp_routes_old;
char *lease_file; char *lease_file;
uint32_t original_mtu; uint32_t original_mtu;
unsigned dhcp4_messages; unsigned dhcp4_messages;
unsigned dhcp4_remove_messages; unsigned dhcp4_remove_messages;
unsigned dhcp6_address_messages;
unsigned dhcp6_route_messages;
unsigned dhcp6_pd_address_messages;
unsigned dhcp6_pd_route_messages;
bool dhcp4_route_failed:1; bool dhcp4_route_failed:1;
bool dhcp4_route_retrying:1; bool dhcp4_route_retrying:1;
bool dhcp4_configured:1; bool dhcp4_configured:1;
bool dhcp4_address_bind:1; bool dhcp4_address_bind:1;
bool dhcp6_address_configured:1;
bool dhcp6_route_configured:1;
bool dhcp6_pd_address_configured:1;
bool dhcp6_pd_route_configured:1;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;
bool ndisc_routes_configured:1;
sd_ipv4ll *ipv4ll; sd_ipv4ll *ipv4ll;
bool ipv4ll_address_configured:1; bool ipv4ll_address:1;
bool addresses_configured:1; bool addresses_configured:1;
bool addresses_ready:1; bool addresses_ready:1;
@ -130,30 +141,10 @@ typedef struct Link {
sd_ndisc *ndisc; sd_ndisc *ndisc;
Set *ndisc_rdnss; Set *ndisc_rdnss;
Set *ndisc_dnssl; Set *ndisc_dnssl;
Set *ndisc_addresses, *ndisc_addresses_old;
Set *ndisc_routes, *ndisc_routes_old;
unsigned ndisc_addresses_messages;
unsigned ndisc_routes_messages;
bool ndisc_addresses_configured:1;
bool ndisc_routes_configured:1;
sd_radv *radv; sd_radv *radv;
sd_dhcp6_client *dhcp6_client; sd_dhcp6_client *dhcp6_client;
sd_dhcp6_lease *dhcp6_lease;
Set *dhcp6_addresses, *dhcp6_addresses_old;
Set *dhcp6_routes, *dhcp6_routes_old;
Set *dhcp6_pd_addresses, *dhcp6_pd_addresses_old;
Set *dhcp6_pd_routes, *dhcp6_pd_routes_old;
unsigned dhcp6_address_messages;
unsigned dhcp6_route_messages;
unsigned dhcp6_pd_address_messages;
unsigned dhcp6_pd_route_messages;
bool dhcp6_address_configured:1;
bool dhcp6_route_configured:1;
bool dhcp6_pd_address_configured:1;
bool dhcp6_pd_route_configured:1;
bool dhcp6_pd_prefixes_assigned:1;
/* This is about LLDP reception */ /* This is about LLDP reception */
sd_lldp *lldp; sd_lldp *lldp;

View File

@ -857,10 +857,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
valid_str ? "for " : "forever", strempty(valid_str)); valid_str ? "for " : "forever", strempty(valid_str));
} }
/* address_update() logs internally, so we don't need to here. */ /* address_update() logs internally, so we don't need to. */
r = address_update(address, flags, scope, &cinfo); (void) address_update(address, flags, scope, &cinfo);
if (r < 0)
link_enter_failed(link);
break; break;
@ -1823,20 +1821,27 @@ int manager_new(Manager **ret) {
} }
void manager_free(Manager *m) { void manager_free(Manager *m) {
struct in6_addr *a;
AddressPool *pool; AddressPool *pool;
Link *link; Link *link;
Iterator i;
if (!m) if (!m)
return; return;
free(m->state_file); free(m->state_file);
HASHMAP_FOREACH(link, m->links, i) while ((a = hashmap_first_key(m->dhcp6_prefixes)))
(void) dhcp6_prefix_remove(m, a);
m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_steal_first(m->links))) {
if (link->dhcp6_client)
(void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client, link);
(void) link_stop_clients(link, true); (void) link_stop_clients(link, true);
m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free); link_unref(link);
m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free); }
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref); m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);
@ -1852,9 +1857,9 @@ void manager_free(Manager *m) {
/* routing_policy_rule_free() access m->rules and m->rules_foreign. /* routing_policy_rule_free() access m->rules and m->rules_foreign.
* So, it is necessary to set NULL after the sets are freed. */ * So, it is necessary to set NULL after the sets are freed. */
m->rules = set_free(m->rules); m->rules = set_free_with_destructor(m->rules, routing_policy_rule_free);
m->rules_foreign = set_free(m->rules_foreign); m->rules_foreign = set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
set_free(m->rules_saved); set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
sd_netlink_unref(m->rtnl); sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl); sd_netlink_unref(m->genl);

View File

@ -44,7 +44,6 @@ struct Manager {
Hashmap *netdevs; Hashmap *netdevs;
OrderedHashmap *networks; OrderedHashmap *networks;
Hashmap *dhcp6_prefixes; Hashmap *dhcp6_prefixes;
Set *dhcp6_pd_prefixes;
LIST_HEAD(AddressPool, address_pools); LIST_HEAD(AddressPool, address_pools);
usec_t network_dirs_ts_usec; usec_t network_dirs_ts_usec;

View File

@ -35,79 +35,6 @@
#define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e) #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
static int ndisc_remove_old(Link *link, bool force);
static int ndisc_address_callback(Address *address) {
Address *a;
Iterator i;
assert(address);
assert(address->link);
/* Make this called only once */
SET_FOREACH(a, address->link->ndisc_addresses, i)
a->callback = NULL;
return ndisc_remove_old(address->link, true);
}
static int ndisc_remove_old(Link *link, bool force) {
Address *address;
Route *route;
NDiscDNSSL *dnssl;
NDiscRDNSS *rdnss;
Iterator i;
int k, r = 0;
assert(link);
if (!force) {
bool set_callback = !set_isempty(link->ndisc_addresses);
if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured)
return 0;
SET_FOREACH(address, link->ndisc_addresses, i)
if (address_is_ready(address)) {
set_callback = false;
break;
}
if (set_callback) {
SET_FOREACH(address, link->ndisc_addresses, i)
address->callback = ndisc_address_callback;
return 0;
}
}
if (!set_isempty(link->ndisc_addresses_old) || !set_isempty(link->ndisc_routes_old))
log_link_debug(link, "Removing old NDisc addresses and routes.");
link_dirty(link);
SET_FOREACH(address, link->ndisc_addresses_old, i) {
k = address_remove(address, link, NULL);
if (k < 0)
r = k;
}
SET_FOREACH(route, link->ndisc_routes_old, i) {
k = route_remove(route, link, NULL);
if (k < 0)
r = k;
}
SET_FOREACH(rdnss, link->ndisc_rdnss, i)
if (rdnss->marked)
free(set_remove(link->ndisc_rdnss, rdnss));
SET_FOREACH(dnssl, link->ndisc_dnssl, i)
if (dnssl->marked)
free(set_remove(link->ndisc_dnssl, dnssl));
return r;
}
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
@ -129,13 +56,6 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
if (link->ndisc_routes_messages == 0) { if (link->ndisc_routes_messages == 0) {
log_link_debug(link, "NDisc routes set."); log_link_debug(link, "NDisc routes set.");
link->ndisc_routes_configured = true; link->ndisc_routes_configured = true;
r = ndisc_remove_old(link, false);
if (r < 0) {
link_enter_failed(link);
return 1;
}
link_check_ready(link); link_check_ready(link);
} }
@ -164,13 +84,6 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
if (link->ndisc_addresses_messages == 0) { if (link->ndisc_addresses_messages == 0) {
log_link_debug(link, "NDisc SLAAC addresses set."); log_link_debug(link, "NDisc SLAAC addresses set.");
link->ndisc_addresses_configured = true; link->ndisc_addresses_configured = true;
r = ndisc_remove_old(link, false);
if (r < 0) {
link_enter_failed(link);
return 1;
}
r = link_request_set_routes(link); r = link_request_set_routes(link);
if (r < 0) { if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
@ -181,50 +94,6 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1; return 1;
} }
static int ndisc_route_configure(Route *route, Link *link) {
Route *ret;
int r;
assert(route);
assert(link);
r = route_configure(route, link, ndisc_route_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
link->ndisc_routes_messages++;
r = set_ensure_put(&link->ndisc_routes, &route_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store NDisc route: %m");
(void) set_remove(link->ndisc_routes_old, ret);
return 0;
}
static int ndisc_address_configure(Address *address, Link *link) {
Address *ret;
int r;
assert(address);
assert(link);
r = address_configure(address, link, ndisc_address_handler, true, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc SLAAC address: %m");
link->ndisc_addresses_messages++;
r = set_ensure_put(&link->ndisc_addresses, &address_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m");
(void) set_remove(link->ndisc_addresses_old, ret);
return 0;
}
static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
union in_addr_union gateway; union in_addr_union gateway;
@ -286,9 +155,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->lifetime = time_now + lifetime * USEC_PER_SEC; route->lifetime = time_now + lifetime * USEC_PER_SEC;
route->mtu = mtu; route->mtu = mtu;
r = ndisc_route_configure(route, link); r = route_configure(route, link, ndisc_route_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set default route: %m"); return log_link_error_errno(link, r, "Could not set default route: %m");
if (r > 0)
link->ndisc_routes_messages++;
Route *route_gw; Route *route_gw;
LIST_FOREACH(routes, route_gw, link->network->static_routes) { LIST_FOREACH(routes, route_gw, link->network->static_routes) {
@ -300,9 +171,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route_gw->gw = gateway; route_gw->gw = gateway;
r = ndisc_route_configure(route_gw, link); r = route_configure(route_gw, link, ndisc_route_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set gateway: %m"); return log_link_error_errno(link, r, "Could not set gateway: %m");
if (r > 0)
link->ndisc_routes_messages++;
} }
return 0; return 0;
@ -514,9 +387,11 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
address->in_addr.in6 = *a; address->in_addr.in6 = *a;
r = ndisc_address_configure(address, link); r = address_configure(address, link, ndisc_address_handler, true);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set SLAAC address: %m"); return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
if (r > 0)
link->ndisc_addresses_messages++;
} }
return 0; return 0;
@ -560,9 +435,11 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m"); return log_link_error_errno(link, r, "Failed to get prefix address: %m");
r = ndisc_route_configure(route, link); r = route_configure(route, link, ndisc_route_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set prefix route: %m");; return log_link_error_errno(link, r, "Could not set prefix route: %m");;
if (r > 0)
link->ndisc_routes_messages++;
return 0; return 0;
} }
@ -617,9 +494,11 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get route address: %m"); return log_link_error_errno(link, r, "Failed to get route address: %m");
r = ndisc_route_configure(route, link); r = route_configure(route, link, ndisc_route_handler);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not set additional route: %m"); return log_link_error_errno(link, r, "Could not set additional route: %m");
if (r > 0)
link->ndisc_routes_messages++;
return 0; return 0;
} }
@ -632,19 +511,12 @@ static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
return memcmp(&a->address, &b->address, sizeof(a->address)); return memcmp(&a->address, &b->address, sizeof(a->address));
} }
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops, NDiscRDNSS, ndisc_rdnss_hash_func, ndisc_rdnss_compare_func);
ndisc_rdnss_hash_ops,
NDiscRDNSS,
ndisc_rdnss_hash_func,
ndisc_rdnss_compare_func,
free);
static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
uint32_t lifetime; uint32_t lifetime;
const struct in6_addr *a; const struct in6_addr *a;
NDiscRDNSS *rdnss;
usec_t time_now; usec_t time_now;
Iterator i;
int n, r; int n, r;
assert(link); assert(link);
@ -662,27 +534,28 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
if (n < 0) if (n < 0)
return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
SET_FOREACH(rdnss, link->ndisc_rdnss, i) for (int i = 0; i < n; i++) {
rdnss->marked = true;
if (lifetime == 0)
return 0;
if (n >= (int) NDISC_RDNSS_MAX) {
log_link_warning(link, "Too many RDNSS records per link. Only first %i records will be used.", NDISC_RDNSS_MAX);
n = NDISC_RDNSS_MAX;
}
for (int j = 0; j < n; j++) {
_cleanup_free_ NDiscRDNSS *x = NULL; _cleanup_free_ NDiscRDNSS *x = NULL;
NDiscRDNSS d = { NDiscRDNSS d = {
.address = a[j], .address = a[i],
}; }, *y;
rdnss = set_get(link->ndisc_rdnss, &d); if (lifetime == 0) {
if (rdnss) { (void) set_remove(link->ndisc_rdnss, &d);
rdnss->marked = false; link_dirty(link);
rdnss->valid_until = time_now + lifetime * USEC_PER_SEC; continue;
}
y = set_get(link->ndisc_rdnss, &d);
if (y) {
y->valid_until = time_now + lifetime * USEC_PER_SEC;
continue;
}
ndisc_vacuum(link);
if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
log_link_warning(link, "Too many RDNSS records per link, ignoring.");
continue; continue;
} }
@ -691,7 +564,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
return log_oom(); return log_oom();
*x = (NDiscRDNSS) { *x = (NDiscRDNSS) {
.address = a[j], .address = a[i],
.valid_until = time_now + lifetime * USEC_PER_SEC, .valid_until = time_now + lifetime * USEC_PER_SEC,
}; };
@ -699,6 +572,8 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
assert(r > 0); assert(r > 0);
link_dirty(link);
} }
return 0; return 0;
@ -712,20 +587,13 @@ static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b)); return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
} }
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops, NDiscDNSSL, ndisc_dnssl_hash_func, ndisc_dnssl_compare_func);
ndisc_dnssl_hash_ops,
NDiscDNSSL,
ndisc_dnssl_hash_func,
ndisc_dnssl_compare_func,
free);
static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
_cleanup_strv_free_ char **l = NULL; _cleanup_strv_free_ char **l = NULL;
uint32_t lifetime; uint32_t lifetime;
usec_t time_now; usec_t time_now;
NDiscDNSSL *dnssl; char **i;
Iterator i;
char **j;
int r; int r;
assert(link); assert(link);
@ -743,31 +611,32 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
SET_FOREACH(dnssl, link->ndisc_dnssl, i) STRV_FOREACH(i, l) {
dnssl->marked = true;
if (lifetime == 0)
return 0;
if (strv_length(l) >= NDISC_DNSSL_MAX) {
log_link_warning(link, "Too many DNSSL records per link. Only first %i records will be used.", NDISC_DNSSL_MAX);
STRV_FOREACH(j, l + NDISC_DNSSL_MAX)
*j = mfree(*j);
}
STRV_FOREACH(j, l) {
_cleanup_free_ NDiscDNSSL *s = NULL; _cleanup_free_ NDiscDNSSL *s = NULL;
NDiscDNSSL *x;
s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1); s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1);
if (!s) if (!s)
return log_oom(); return log_oom();
strcpy(NDISC_DNSSL_DOMAIN(s), *j); strcpy(NDISC_DNSSL_DOMAIN(s), *i);
dnssl = set_get(link->ndisc_dnssl, s); if (lifetime == 0) {
if (dnssl) { (void) set_remove(link->ndisc_dnssl, s);
dnssl->marked = false; link_dirty(link);
dnssl->valid_until = time_now + lifetime * USEC_PER_SEC; continue;
}
x = set_get(link->ndisc_dnssl, s);
if (x) {
x->valid_until = time_now + lifetime * USEC_PER_SEC;
continue;
}
ndisc_vacuum(link);
if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
log_link_warning(link, "Too many DNSSL records per link, ignoring.");
continue; continue;
} }
@ -777,6 +646,8 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
assert(r > 0); assert(r > 0);
link_dirty(link);
} }
return 0; return 0;
@ -865,8 +736,6 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
} }
static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
Address *address;
Route *route;
uint64_t flags; uint64_t flags;
int r; int r;
@ -875,23 +744,6 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
assert(link->manager); assert(link->manager);
assert(rt); assert(rt);
link->ndisc_addresses_configured = false;
link->ndisc_routes_configured = false;
link_dirty(link);
while ((address = set_steal_first(link->ndisc_addresses))) {
r = set_ensure_put(&link->ndisc_addresses_old, &address_hash_ops, address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store old NDisc SLAAC address: %m");
}
while ((route = set_steal_first(link->ndisc_routes))) {
r = set_ensure_put(&link->ndisc_routes_old, &route_hash_ops, route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store old NDisc route: %m");
}
r = sd_ndisc_router_get_flags(rt, &flags); r = sd_ndisc_router_get_flags(rt, &flags);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get RA flags: %m"); return log_link_error_errno(link, r, "Failed to get RA flags: %m");
@ -905,8 +757,10 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED)); r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
if (r < 0 && r != -EBUSY) if (r < 0 && r != -EBUSY)
return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
else else {
log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request"); log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
r = 0;
}
} }
r = ndisc_router_process_default(link, rt); r = ndisc_router_process_default(link, rt);
@ -916,6 +770,30 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return r; return r;
return r;
}
static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
Link *link = userdata;
int r;
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return;
switch (event) {
case SD_NDISC_EVENT_ROUTER:
link->ndisc_addresses_configured = false;
link->ndisc_routes_configured = false;
r = ndisc_router_handler(link, rt);
if (r < 0) {
link_enter_failed(link);
return;
}
if (link->ndisc_addresses_messages == 0) if (link->ndisc_addresses_messages == 0)
link->ndisc_addresses_configured = true; link->ndisc_addresses_configured = true;
else { else {
@ -933,44 +811,18 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
else else
log_link_debug(link, "Setting NDisc routes."); log_link_debug(link, "Setting NDisc routes.");
r = ndisc_remove_old(link, false);
if (r < 0)
return r;
if (link->ndisc_addresses_configured && link->ndisc_routes_configured) if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
link_check_ready(link); link_check_ready(link);
else else
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
return 0;
}
static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
Link *link = userdata;
int r;
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return;
switch (event) {
case SD_NDISC_EVENT_ROUTER:
r = ndisc_router_handler(link, rt);
if (r < 0) {
link_enter_failed(link);
return;
}
break; break;
case SD_NDISC_EVENT_TIMEOUT: case SD_NDISC_EVENT_TIMEOUT:
log_link_debug(link, "NDisc handler get timeout event"); log_link_debug(link, "NDisc handler get timeout event");
if (link->ndisc_addresses_messages == 0 && link->ndisc_routes_messages == 0) {
link->ndisc_addresses_configured = true; link->ndisc_addresses_configured = true;
link->ndisc_routes_configured = true; link->ndisc_routes_configured = true;
link_check_ready(link); link_check_ready(link);
}
break; break;
default: default:
assert_not_reached("Unknown NDisc event"); assert_not_reached("Unknown NDisc event");
@ -1010,7 +862,6 @@ void ndisc_vacuum(Link *link) {
NDiscDNSSL *d; NDiscDNSSL *d;
Iterator i; Iterator i;
usec_t time_now; usec_t time_now;
bool updated = false;
assert(link); assert(link);
@ -1021,17 +872,14 @@ void ndisc_vacuum(Link *link) {
SET_FOREACH(r, link->ndisc_rdnss, i) SET_FOREACH(r, link->ndisc_rdnss, i)
if (r->valid_until < time_now) { if (r->valid_until < time_now) {
free(set_remove(link->ndisc_rdnss, r)); free(set_remove(link->ndisc_rdnss, r));
updated = true; link_dirty(link);
} }
SET_FOREACH(d, link->ndisc_dnssl, i) SET_FOREACH(d, link->ndisc_dnssl, i)
if (d->valid_until < time_now) { if (d->valid_until < time_now) {
free(set_remove(link->ndisc_dnssl, d)); free(set_remove(link->ndisc_dnssl, d));
updated = true;
}
if (updated)
link_dirty(link); link_dirty(link);
}
} }
void ndisc_flush(Link *link) { void ndisc_flush(Link *link) {
@ -1039,8 +887,8 @@ void ndisc_flush(Link *link) {
/* Removes all RDNSS and DNSSL entries, without exception */ /* Removes all RDNSS and DNSSL entries, without exception */
link->ndisc_rdnss = set_free(link->ndisc_rdnss); link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
link->ndisc_dnssl = set_free(link->ndisc_dnssl); link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
} }
int ipv6token_new(IPv6Token **ret) { int ipv6token_new(IPv6Token **ret) {

View File

@ -24,15 +24,11 @@ typedef enum IPv6AcceptRAStartDHCP6Client {
} IPv6AcceptRAStartDHCP6Client; } IPv6AcceptRAStartDHCP6Client;
typedef struct NDiscRDNSS { typedef struct NDiscRDNSS {
/* Used when GC'ing old DNS servers when configuration changes. */
bool marked;
usec_t valid_until; usec_t valid_until;
struct in6_addr address; struct in6_addr address;
} NDiscRDNSS; } NDiscRDNSS;
typedef struct NDiscDNSSL { typedef struct NDiscDNSSL {
/* Used when GC'ing old domains when configuration changes. */
bool marked;
usec_t valid_until; usec_t valid_until;
/* The domain name follows immediately. */ /* The domain name follows immediately. */
} NDiscDNSSL; } NDiscDNSSL;

View File

@ -247,7 +247,7 @@ static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size); return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size);
} }
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free); DEFINE_PRIVATE_HASH_OPS(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func);
int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) {
Neighbor neighbor, *existing; Neighbor neighbor, *existing;

View File

@ -213,6 +213,8 @@ DHCPv6.UserClass, config_parse_dhcp_user_class,
DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class) DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class)
DHCPv6.SendVendorOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_vendor_options) DHCPv6.SendVendorOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_vendor_options)
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv6.AssignAcquiredDelegatedPrefixAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign_prefix)
DHCPv6.AssignAcquiredDelegatedPrefixToken, config_parse_dhcp6_delegated_prefix_token, 0, 0
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0 DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_without_ra) DHCPv6.WithoutRA, config_parse_dhcp6_client_start_mode, 0, offsetof(Network, dhcp6_without_ra)
DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options) DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options)
@ -269,9 +271,7 @@ BridgeVLAN.PVID, config_parse_brvlan_pvid,
BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation) Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id, 0, offsetof(Network, dhcp6_pd_subnet_id) Network.IPv6PDSubnetId, config_parse_router_prefix_subnet_id, 0, 0
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign)
DHCPv6PrefixDelegation.Token, config_parse_dhcp6_pd_token, 0, offsetof(Network, dhcp6_pd_token)
IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed) IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information)

View File

@ -420,8 +420,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp6_use_ntp = true, .dhcp6_use_ntp = true,
.dhcp6_use_dns = true, .dhcp6_use_dns = true,
.dhcp6_pd_subnet_id = -1, .dhcp6_pd_assign_prefix = true,
.dhcp6_pd_assign = true,
.dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true, .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
.dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true, .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
@ -430,6 +429,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp_server_emit_router = true, .dhcp_server_emit_router = true,
.dhcp_server_emit_timezone = true, .dhcp_server_emit_timezone = true,
.router_prefix_subnet_id = -1,
.router_emit_dns = true, .router_emit_dns = true,
.router_emit_domains = true, .router_emit_domains = true,

View File

@ -184,6 +184,7 @@ struct Network {
/* IPv6 prefix delegation support */ /* IPv6 prefix delegation support */
RADVPrefixDelegation router_prefix_delegation; RADVPrefixDelegation router_prefix_delegation;
int64_t router_prefix_subnet_id;
usec_t router_lifetime_usec; usec_t router_lifetime_usec;
uint8_t router_preference; uint8_t router_preference;
bool router_managed; bool router_managed;
@ -197,11 +198,8 @@ struct Network {
bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O' bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O'
RA flag is set, see RFC 7084, RA flag is set, see RFC 7084,
WPD-4 */ WPD-4 */
bool dhcp6_pd_assign_prefix;
/* DHCPv6 Prefix Delegation support */ union in_addr_union dhcp6_delegation_prefix_token;
int64_t dhcp6_pd_subnet_id;
bool dhcp6_pd_assign;
union in_addr_union dhcp6_pd_token;
/* Bridge Support */ /* Bridge Support */
int use_bpdu; int use_bpdu;

View File

@ -650,7 +650,10 @@ int radv_configure(Link *link) {
return r; return r;
} }
if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) { if (IN_SET(link->network->router_prefix_delegation,
RADV_PREFIX_DELEGATION_STATIC,
RADV_PREFIX_DELEGATION_BOTH)) {
LIST_FOREACH(prefixes, p, link->network->static_prefixes) { LIST_FOREACH(prefixes, p, link->network->static_prefixes) {
r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); r = sd_radv_add_prefix(link->radv, p->radv_prefix, false);
if (r == -EEXIST) if (r == -EEXIST)
@ -670,12 +673,13 @@ int radv_configure(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
} }
} }
return 0; return 0;
} }
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid) { uint32_t lifetime_preferred, uint32_t lifetime_valid) {
_cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL; _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
int r; int r;
@ -866,3 +870,46 @@ int config_parse_router_preference(const char *unit,
return 0; return 0;
} }
int config_parse_router_prefix_subnet_id(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
uint64_t t;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue) || streq(rvalue, "auto")) {
network->router_prefix_subnet_id = -1;
return 0;
}
r = safe_atoux64(rvalue, &t);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (t > INT64_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid subnet id '%s', ignoring assignment.",
rvalue);
return 0;
}
network->router_prefix_subnet_id = (int64_t)t;
return 0;
}

View File

@ -14,10 +14,10 @@ typedef struct Prefix Prefix;
typedef struct RoutePrefix RoutePrefix; typedef struct RoutePrefix RoutePrefix;
typedef enum RADVPrefixDelegation { typedef enum RADVPrefixDelegation {
RADV_PREFIX_DELEGATION_NONE = 0, RADV_PREFIX_DELEGATION_NONE,
RADV_PREFIX_DELEGATION_STATIC = 1 << 0, RADV_PREFIX_DELEGATION_STATIC,
RADV_PREFIX_DELEGATION_DHCP6 = 1 << 1, RADV_PREFIX_DELEGATION_DHCP6,
RADV_PREFIX_DELEGATION_BOTH = RADV_PREFIX_DELEGATION_STATIC | RADV_PREFIX_DELEGATION_DHCP6, RADV_PREFIX_DELEGATION_BOTH,
_RADV_PREFIX_DELEGATION_MAX, _RADV_PREFIX_DELEGATION_MAX,
_RADV_PREFIX_DELEGATION_INVALID = -1, _RADV_PREFIX_DELEGATION_INVALID = -1,
} RADVPrefixDelegation; } RADVPrefixDelegation;
@ -52,7 +52,7 @@ 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, const struct in6_addr *prefix, uint8_t prefix_len, int radv_add_prefix(Link *link, struct in6_addr *prefix, uint8_t prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_valid); 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_;
@ -60,6 +60,7 @@ RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation); CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
CONFIG_PARSER_PROTOTYPE(config_parse_router_preference); CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_subnet_id);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix); CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);

View File

@ -144,14 +144,6 @@ void route_free(Route *route) {
if (route->link) { if (route->link) {
set_remove(route->link->routes, route); set_remove(route->link->routes, route);
set_remove(route->link->routes_foreign, route); set_remove(route->link->routes_foreign, route);
set_remove(route->link->dhcp_routes, route);
set_remove(route->link->dhcp_routes_old, route);
set_remove(route->link->dhcp6_routes, route);
set_remove(route->link->dhcp6_routes_old, route);
set_remove(route->link->dhcp6_pd_routes, route);
set_remove(route->link->dhcp6_pd_routes_old, route);
set_remove(route->link->ndisc_routes, route);
set_remove(route->link->ndisc_routes_old, route);
} }
ordered_set_free_free(route->multipath_routes); ordered_set_free_free(route->multipath_routes);
@ -605,8 +597,7 @@ static int append_nexthops(Route *route, sd_netlink_message *req) {
int route_configure( int route_configure(
Route *route, Route *route,
Link *link, Link *link,
link_netlink_message_handler_t callback, link_netlink_message_handler_t callback) {
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
@ -812,9 +803,6 @@ int route_configure(
sd_event_source_unref(route->expire); sd_event_source_unref(route->expire);
route->expire = TAKE_PTR(expire); route->expire = TAKE_PTR(expire);
if (ret)
*ret = route;
return 1; return 1;
} }

View File

@ -66,7 +66,7 @@ extern const struct hash_ops route_hash_ops;
int route_new(Route **ret); int route_new(Route **ret);
void route_free(Route *route); void route_free(Route *route);
int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret); int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback);
int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback);
int route_get(Link *link, Route *in, Route **ret); int route_get(Link *link, Route *in, Route **ret);

View File

@ -227,12 +227,7 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
} }
} }
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops, RoutingPolicyRule, routing_policy_rule_hash_func, routing_policy_rule_compare_func);
routing_policy_rule_hash_ops,
RoutingPolicyRule,
routing_policy_rule_hash_func,
routing_policy_rule_compare_func,
routing_policy_rule_free);
int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) {

View File

@ -53,7 +53,7 @@ static void test_rule_serialization(const char *title, const char *ruleset, cons
log_info("$ %s", cmd); log_info("$ %s", cmd);
assert_se(system(cmd) == 0); assert_se(system(cmd) == 0);
set_free(rules); set_free_with_destructor(rules, routing_policy_rule_free);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {

View File

@ -8,27 +8,21 @@
#include "errno-util.h" #include "errno-util.h"
#include "macro.h" #include "macro.h"
/* 4MB for contents of regular files, 64k inodes for directories, symbolic links and device specials, using /* 4MB for contents of regular files, 64k inodes for directories, symbolic links and device specials,
* large storage array systems as a baseline */ using large storage array systems as a baseline */
#define TMPFS_LIMITS_DEV ",size=4m,nr_inodes=64k" #define TMPFS_LIMITS_DEV ",size=4m,nr_inodes=64k"
/* Very little, if any use expected */ /* Very little, if any use expected */
#define TMPFS_LIMITS_EMPTY_OR_ALMOST ",size=4m,nr_inodes=1k" #define TMPFS_LIMITS_EMPTY_OR_ALMOST ",size=4m,nr_inodes=1k"
#define TMPFS_LIMITS_SYS TMPFS_LIMITS_EMPTY_OR_ALMOST #define TMPFS_LIMITS_SYS TMPFS_LIMITS_EMPTY_OR_ALMOST
#define TMPFS_LIMITS_SYS_FS_CGROUP TMPFS_LIMITS_EMPTY_OR_ALMOST #define TMPFS_LIMITS_SYS_FS_CGROUP TMPFS_LIMITS_EMPTY_OR_ALMOST
/* On an extremely small device with only 256MB of RAM, 20% of RAM for /run should be enough for re-exec of
/* On an extremely small device with only 256MB of RAM, 20% of RAM should be enough for the re-execution of PID1 because 16MB of free space is required. */
* PID1 because 16MB of free space is required. */
#define TMPFS_LIMITS_RUN ",size=20%,nr_inodes=800k" #define TMPFS_LIMITS_RUN ",size=20%,nr_inodes=800k"
/* 10% of RAM (using 16GB of RAM as a baseline) translates to 400k inodes (assuming 4k each) and 25%
/* The limit used for various tmpfs mounts, but not /tmp itself. translates to 1M inodes */
* 10% of RAM (using 16GB of RAM as a baseline) translates to 400k inodes (assuming 4k each) and 25%
* translates to 1M inodes.
* /tmp is configured through a .mount unit file. */
#define TMPFS_LIMITS_TMP ",size=10%,nr_inodes=400k" #define TMPFS_LIMITS_TMP ",size=10%,nr_inodes=400k"
#define TMPFS_LIMITS_DEV_SHM TMPFS_LIMITS_TMP #define TMPFS_LIMITS_DEV_SHM TMPFS_LIMITS_TMP
#define TMPFS_LIMITS_TEMPORARY_FS TMPFS_LIMITS_TMP #define TMPFS_LIMITS_TEMPORARY_FS TMPFS_LIMITS_TMP
/* More space for volatile root and /var */ /* More space for volatile root and /var */
#define TMPFS_LIMITS_VAR ",size=25%,nr_inodes=1m" #define TMPFS_LIMITS_VAR ",size=25%,nr_inodes=1m"
#define TMPFS_LIMITS_ROOTFS TMPFS_LIMITS_VAR #define TMPFS_LIMITS_ROOTFS TMPFS_LIMITS_VAR

View File

@ -125,16 +125,10 @@ int can_sleep_state(char **types) {
k = strlen(*type); k = strlen(*type);
FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state)
if (l == k && memcmp(word, *type, l) == 0) { if (l == k && memcmp(word, *type, l) == 0)
log_debug("Sleep mode \"%s\" is supported by the kernel.", *type);
return true; return true;
} }
}
if (DEBUG_LOGGING) {
_cleanup_free_ char *t = strv_join(types, "/");
log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t));
}
return false; return false;
} }

View File

@ -23,7 +23,7 @@ static void check_p_d_u(const char *path, int code, const char *result) {
int r; int r;
r = cg_path_decode_unit(path, &unit); r = cg_path_decode_unit(path, &unit);
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(result), code); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
assert_se(r == code); assert_se(r == code);
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }
@ -45,7 +45,7 @@ static void check_p_g_u(const char *path, int code, const char *result) {
int r; int r;
r = cg_path_get_unit(path, &unit); r = cg_path_get_unit(path, &unit);
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(result), code); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
assert_se(r == code); assert_se(r == code);
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }
@ -69,7 +69,7 @@ static void check_p_g_u_u(const char *path, int code, const char *result) {
int r; int r;
r = cg_path_get_user_unit(path, &unit); r = cg_path_get_user_unit(path, &unit);
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(result), code); printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
assert_se(r == code); assert_se(r == code);
assert_se(streq_ptr(unit, result)); assert_se(streq_ptr(unit, result));
} }

View File

@ -864,17 +864,14 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
} }
static void test_path_is_encrypted(void) { static void test_path_is_encrypted(void) {
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a log_info("/* %s */", __func__);
* reguar fs. Don't assume too much if not running under systemd. */
log_info("/* %s (sd_booted=%d)*/", __func__, booted);
test_path_is_encrypted_one("/home", -1); test_path_is_encrypted_one("/home", -1);
test_path_is_encrypted_one("/var", -1); test_path_is_encrypted_one("/var", -1);
test_path_is_encrypted_one("/", -1); test_path_is_encrypted_one("/", -1);
test_path_is_encrypted_one("/proc", false); test_path_is_encrypted_one("/proc", false);
test_path_is_encrypted_one("/sys", false); test_path_is_encrypted_one("/sys", false);
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1); test_path_is_encrypted_one("/dev", false);
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {

View File

@ -79,15 +79,21 @@ static Service *service_for_path(Manager *m, Path *path, const char *service_nam
} }
static void check_states(Manager *m, Path *path, Service *service, PathState path_state, ServiceState service_state) { static void check_states(Manager *m, Path *path, Service *service, PathState path_state, ServiceState service_state) {
usec_t ts;
usec_t timeout = 2 * USEC_PER_SEC;
assert_se(m); assert_se(m);
assert_se(service); assert_se(service);
usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC; ts = now(CLOCK_MONOTONIC);
while (path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS || while (path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS ||
path->state != path_state || service->state != service_state) { path->state != path_state || service->state != service_state) {
usec_t n;
int r;
assert_se(sd_event_run(m->event, 100 * USEC_PER_MSEC) >= 0); r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
assert_se(r >= 0);
printf("%s: state = %s; result = %s \n", printf("%s: state = %s; result = %s \n",
UNIT(path)->id, UNIT(path)->id,
@ -98,7 +104,8 @@ static void check_states(Manager *m, Path *path, Service *service, PathState pat
service_state_to_string(service->state), service_state_to_string(service->state),
service_result_to_string(service->result)); service_result_to_string(service->result));
if (now(CLOCK_MONOTONIC) >= end) { n = now(CLOCK_MONOTONIC);
if (ts + timeout < n) {
log_error("Test timeout when testing %s", UNIT(path)->id); log_error("Test timeout when testing %s", UNIT(path)->id);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -7,7 +7,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "efivars.h"
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "log.h" #include "log.h"
@ -85,9 +84,7 @@ static void test_sleep(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot())); log_info("/= configuration =/");
log_info("/= individual sleep modes =/");
log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0)); log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0));
log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0)); log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0));
log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0)); log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0));
@ -97,7 +94,7 @@ static void test_sleep(void) {
log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0)); log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0));
log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0)); log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0));
log_info("/= high-level sleep verbs =/"); log_info("/= running system =/");
r = can_sleep("suspend"); r = can_sleep("suspend");
log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("hibernate"); r = can_sleep("hibernate");

View File

@ -130,12 +130,10 @@ SendOption=
RequestOptions= RequestOptions=
UserClass= UserClass=
VendorClass= VendorClass=
AssignAcquiredDelegatedPrefixAddress=
AssignAcquiredDelegatedPrefixToken=
SendVendorOption= SendVendorOption=
RouteMetric= RouteMetric=
[DHCPv6PrefixDelegation]
SubnetId=
Assign=
Token=
[Route] [Route]
Destination= Destination=
Protocol= Protocol=
@ -205,6 +203,7 @@ NTP=
DHCP= DHCP=
Domains= Domains=
IPv6PrefixDelegation= IPv6PrefixDelegation=
IPv6PDSubnetId=
VLAN= VLAN=
DHCPServer= DHCPServer=
BindCarrier= BindCarrier=

View File

@ -1,26 +0,0 @@
[Match]
Name=dummy98
[Network]
IPv6AcceptRA=no
VRF=vrf99
Address=fdde:11:22::1/128
Address=fdde:11:33::1/64
Address=10.20.22.1/32
Address=10.20.33.1/24
[Address]
Address=fdde:11:44::1/128
AddPrefixRoute=no
[Address]
Address=fdde:11:55::1/64
AddPrefixRoute=no
[Address]
Address=10.20.44.1/32
AddPrefixRoute=no
[Address]
Address=10.20.55.1/24
AddPrefixRoute=no

View File

@ -1,25 +0,0 @@
[Match]
Name=test1
[Network]
IPv6AcceptRA=no
Address=fdde:12:22::1/128
Address=fdde:12:33::1/64
Address=10.21.22.1/32
Address=10.21.33.1/24
[Address]
Address=fdde:12:44::1/128
AddPrefixRoute=no
[Address]
Address=fdde:12:55::1/64
AddPrefixRoute=no
[Address]
Address=10.21.44.1/32
AddPrefixRoute=no
[Address]
Address=10.21.55.1/24
AddPrefixRoute=no

View File

@ -1717,8 +1717,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-qdisc-ingress-netem-compat.network', '25-qdisc-ingress-netem-compat.network',
'25-qdisc-pie.network', '25-qdisc-pie.network',
'25-qdisc-qfq.network', '25-qdisc-qfq.network',
'25-prefix-route-with-vrf.network',
'25-prefix-route-without-vrf.network',
'25-route-ipv6-src.network', '25-route-ipv6-src.network',
'25-route-static.network', '25-route-static.network',
'25-route-vrf.network', '25-route-vrf.network',
@ -1731,7 +1729,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-veth-peer.network', '25-veth-peer.network',
'25-veth.netdev', '25-veth.netdev',
'25-vrf.netdev', '25-vrf.netdev',
'25-vrf.network',
'26-link-local-addressing-ipv6.network', '26-link-local-addressing-ipv6.network',
'routing-policy-rule-dummy98.network', 'routing-policy-rule-dummy98.network',
'routing-policy-rule-test1.network'] 'routing-policy-rule-test1.network']
@ -1818,77 +1815,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertNotRegex(output, '192.168.100.10/24') self.assertNotRegex(output, '192.168.100.10/24')
@expectedFailureIfModuleIsNotAvailable('vrf')
def test_prefix_route(self):
copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
'25-prefix-route-without-vrf.network', '11-dummy.netdev',
'25-vrf.netdev', '25-vrf.network')
for trial in range(2):
if trial == 0:
start_networkd()
else:
restart_networkd(3)
self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
output = check_output('ip route show table 42 dev dummy98')
print('### ip route show table 42 dev dummy98')
print(output)
self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1')
self.assertRegex(output, 'broadcast 10.20.33.0 proto kernel scope link src 10.20.33.1')
self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1')
self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1')
self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1')
self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1')
self.assertRegex(output, 'broadcast 10.20.55.0 proto kernel scope link src 10.20.55.1')
self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1')
self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1')
output = check_output('ip -6 route show table 42 dev dummy98')
print('### ip -6 route show table 42 dev dummy98')
print(output)
if trial == 0:
# Kernel's bug?
self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium')
#self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium')
self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium')
self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
self.assertRegex(output, 'ff00::/8 metric 256 pref medium')
print()
output = check_output('ip route show dev test1')
print('### ip route show dev test1')
print(output)
self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1')
output = check_output('ip route show table local dev test1')
print('### ip route show table local dev test1')
print(output)
self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1')
self.assertRegex(output, 'broadcast 10.21.33.0 proto kernel scope link src 10.21.33.1')
self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1')
self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1')
self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1')
self.assertRegex(output, 'broadcast 10.21.55.0 proto kernel scope link src 10.21.55.1')
self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1')
self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1')
output = check_output('ip -6 route show dev test1')
print('### ip -6 route show dev test1')
print(output)
self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium')
self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium')
self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
output = check_output('ip -6 route show table local dev test1')
print('### ip -6 route show table local dev test1')
print(output)
self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
self.assertRegex(output, 'ff00::/8 metric 256 pref medium')
def test_configure_without_carrier(self): def test_configure_without_carrier(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev') copy_unit_to_networkd_unit_path('11-dummy.netdev')
start_networkd() start_networkd()

View File

@ -22,4 +22,4 @@ After=swap.target
What=tmpfs What=tmpfs
Where=/tmp Where=/tmp
Type=tmpfs Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=400k Options=mode=1777,strictatime,nosuid,nodev,size=10%,nr_inodes=400k