Compare commits
29 Commits
31363bd564
...
0cfb490fe9
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 0cfb490fe9 | |
Lennart Poettering | ee56c072b9 | |
Lennart Poettering | f8528230b3 | |
Gaurav Singh | b1d666ac58 | |
Daan De Meyer | f649325ba7 | |
Zbigniew Jędrzejewski-Szmek | c550cb7f8c | |
Zbigniew Jędrzejewski-Szmek | 02e1eb6d02 | |
Zbigniew Jędrzejewski-Szmek | 362a55fc14 | |
Yu Watanabe | 99e015e28c | |
Yu Watanabe | 61c0ef4ff3 | |
Yu Watanabe | ea121d8f25 | |
Yu Watanabe | e55265184b | |
Yu Watanabe | 15797d6a2b | |
Yu Watanabe | 1633c45731 | |
Yu Watanabe | 1c09d84e42 | |
Yu Watanabe | b0b9776656 | |
Yu Watanabe | 69203fba70 | |
Yu Watanabe | 6e537f62d7 | |
Yu Watanabe | 80b0e86084 | |
Yu Watanabe | 8eec0b9da5 | |
Yu Watanabe | 5f58af25e6 | |
Yu Watanabe | 3336e946da | |
Yu Watanabe | 5d8c3ec1e9 | |
Yu Watanabe | 97f000744f | |
Yu Watanabe | c9d223e803 | |
Yu Watanabe | 3606ca659e | |
Zbigniew Jędrzejewski-Szmek | c21ed6812e | |
Zbigniew Jędrzejewski-Szmek | 500727c220 | |
Zbigniew Jędrzejewski-Szmek | 933ab8199d |
4
NEWS
4
NEWS
|
@ -112,6 +112,10 @@ 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
|
||||||
|
|
|
@ -809,16 +809,6 @@
|
||||||
<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).
|
||||||
|
@ -1893,25 +1883,6 @@
|
||||||
</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>
|
||||||
|
@ -1966,6 +1937,48 @@
|
||||||
</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
|
||||||
|
|
|
@ -999,16 +999,19 @@ 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"
|
||||||
|
|
|
@ -217,7 +217,7 @@ static int send_ra(uint8_t flags) {
|
||||||
advertisement[5] = flags;
|
advertisement[5] = flags;
|
||||||
|
|
||||||
assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
|
assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
|
||||||
sizeof(advertisement));
|
sizeof(advertisement));
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf(" sent RA with flag 0x%02x\n", flags);
|
printf(" sent RA with flag 0x%02x\n", flags);
|
||||||
|
@ -291,8 +291,8 @@ 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 + 2 *USEC_PER_SEC, 0,
|
time_now + 30 * 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);
|
||||||
assert_se(sd_ndisc_start(nd) >= 0);
|
assert_se(sd_ndisc_start(nd) >= 0);
|
||||||
|
@ -393,8 +393,8 @@ 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 + 2U * USEC_PER_SEC, 0,
|
time_now + 30 * 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);
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,17 @@ 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));
|
||||||
|
@ -205,7 +216,7 @@ static int address_compare_func(const Address *a1, const Address *a2) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
|
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
|
||||||
|
|
||||||
bool address_equal(Address *a1, Address *a2) {
|
bool address_equal(Address *a1, Address *a2) {
|
||||||
if (a1 == a2)
|
if (a1 == a2)
|
||||||
|
@ -344,11 +355,8 @@ 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);
|
||||||
|
|
||||||
|
@ -356,18 +364,27 @@ 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 &&
|
if (!ready && address_is_ready(address)) {
|
||||||
address_is_ready(address) &&
|
if (address->callback) {
|
||||||
address->family == AF_INET6 &&
|
r = address->callback(address);
|
||||||
in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
|
if (r < 0)
|
||||||
in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
|
if (address->family == AF_INET6 &&
|
||||||
if (r < 0)
|
in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
|
||||||
return r;
|
IN6_IS_ADDR_UNSPECIFIED(&address->link->ipv6ll_address) > 0) {
|
||||||
|
|
||||||
|
r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -586,9 +603,11 @@ 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);
|
||||||
|
@ -609,6 +628,13 @@ 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);
|
||||||
|
@ -690,9 +716,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, NULL);
|
r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a);
|
||||||
else
|
else
|
||||||
r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
|
r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a);
|
||||||
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");
|
||||||
|
@ -712,6 +738,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ 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;
|
||||||
|
@ -47,6 +48,9 @@ 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);
|
||||||
|
@ -60,7 +64,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);
|
int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret);
|
||||||
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);
|
||||||
|
|
|
@ -20,38 +20,58 @@
|
||||||
#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 void dhcp4_release_old_lease(Link *link) {
|
static int dhcp4_address_callback(Address *address) {
|
||||||
struct in_addr address = {}, address_old = {};
|
assert(address);
|
||||||
|
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_lease_old)
|
if (!link->dhcp_address_old && set_isempty(link->dhcp_routes_old))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
assert(link->dhcp_lease);
|
if (!force && (link->dhcp_address && !address_is_ready(link->dhcp_address))) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
(void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old);
|
log_link_debug(link, "Removing old DHCPv4 address and routes.");
|
||||||
(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;
|
||||||
|
|
||||||
|
@ -59,8 +79,14 @@ 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. */
|
||||||
dhcp4_release_old_lease(link);
|
r = dhcp4_release_old_lease(link, false);
|
||||||
|
if (r < 0) {
|
||||||
|
link_enter_failed(link);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
link_check_ready(link);
|
link_check_ready(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,27 +150,25 @@ 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);
|
||||||
|
|
||||||
if (set_contains(link->dhcp_routes, *route))
|
r = route_configure(route, link, dhcp4_route_handler, &ret);
|
||||||
return 0;
|
if (r < 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_put(link->dhcp_routes, *route);
|
r = set_ensure_put(&link->dhcp_routes, &route_hash_ops, ret);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_link_error_errno(link, r, "Failed to store DHCPv4 route: %m");
|
||||||
|
|
||||||
|
(void) set_remove(link->dhcp_routes_old, ret);
|
||||||
|
|
||||||
TAKE_PTR(*route);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +211,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");
|
||||||
}
|
}
|
||||||
|
@ -231,6 +255,7 @@ 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);
|
||||||
|
|
||||||
|
@ -245,12 +270,11 @@ 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;
|
||||||
|
|
||||||
r = set_ensure_allocated(&link->dhcp_routes, &route_hash_ops);
|
while ((rt = set_steal_first(link->dhcp_routes))) {
|
||||||
if (r < 0)
|
r = set_ensure_put(&link->dhcp_routes_old, &route_hash_ops, rt);
|
||||||
return log_oom();
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m");
|
||||||
/* 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);
|
||||||
|
|
||||||
|
@ -265,7 +289,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");
|
||||||
}
|
}
|
||||||
|
@ -316,7 +340,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");
|
||||||
}
|
}
|
||||||
|
@ -356,7 +380,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");
|
||||||
|
|
||||||
|
@ -372,12 +396,11 @@ 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;
|
||||||
|
@ -387,272 +410,15 @@ static int link_set_dhcp_routes(Link *link) {
|
||||||
|
|
||||||
rt->gw.in = router[0];
|
rt->gw.in = router[0];
|
||||||
|
|
||||||
r = route_configure(rt, link, dhcp4_route_handler);
|
r = dhcp_route_configure(rt, link);
|
||||||
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;
|
||||||
|
@ -756,37 +522,33 @@ 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) {
|
||||||
struct in_addr address;
|
Route *route;
|
||||||
int r;
|
Iterator i;
|
||||||
|
int k, r = 0;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(link->dhcp_lease);
|
|
||||||
|
|
||||||
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
|
SET_FOREACH(route, link->dhcp_routes, i) {
|
||||||
if (r < 0)
|
k = route_remove(route, link, dhcp4_remove_route_handler);
|
||||||
return log_link_error_errno(link, r, "Failed to get DHCPv4 address: %m");
|
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 (link->dhcp_address) {
|
||||||
if (r < 0)
|
k = address_remove(link->dhcp_address, link, dhcp4_remove_address_handler);
|
||||||
return r;
|
if (k < 0)
|
||||||
|
r = k;
|
||||||
|
else
|
||||||
|
link->dhcp4_remove_messages++;
|
||||||
|
}
|
||||||
|
|
||||||
r = dhcp_remove_router(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
|
return r;
|
||||||
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 r;
|
int k, r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(link->dhcp_lease);
|
assert(link->dhcp_lease);
|
||||||
|
@ -796,24 +558,26 @@ 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. */
|
||||||
dhcp4_release_old_lease(link);
|
k = dhcp4_release_old_lease(link, true);
|
||||||
|
if (k < 0)
|
||||||
|
r = k;
|
||||||
|
|
||||||
r = dhcp4_remove_all(link);
|
k = dhcp4_remove_all(link);
|
||||||
if (r < 0)
|
if (k < 0)
|
||||||
return r;
|
r = k;
|
||||||
|
|
||||||
r = dhcp_reset_mtu(link);
|
k = dhcp_reset_mtu(link);
|
||||||
if (r < 0)
|
if (k < 0)
|
||||||
return r;
|
r = k;
|
||||||
|
|
||||||
r = dhcp_reset_hostname(link);
|
k = dhcp_reset_hostname(link);
|
||||||
if (r < 0)
|
if (k < 0)
|
||||||
return r;
|
r = k;
|
||||||
|
|
||||||
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 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -975,6 +739,7 @@ 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);
|
||||||
|
@ -1049,9 +814,13 @@ 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);
|
r = address_configure(addr, link, dhcp4_address_handler, true, &ret);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_link_error_errno(link, r, "Failed to set DHCPv4 address: %m");
|
||||||
|
|
||||||
|
if (!address_equal(link->dhcp_address, ret))
|
||||||
|
link->dhcp_address_old = link->dhcp_address;
|
||||||
|
link->dhcp_address = ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1151,32 +920,11 @@ 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;
|
||||||
|
|
||||||
link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
|
|
||||||
|
|
||||||
/* 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);
|
r = dhcp_lease_acquired(client, link);
|
||||||
if (r < 0) {
|
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);
|
(void) dhcp_lease_lost(link);
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
@ -17,17 +17,26 @@ typedef enum DHCP6ClientStartMode {
|
||||||
typedef struct Link Link;
|
typedef struct Link Link;
|
||||||
typedef struct Manager Manager;
|
typedef struct Manager Manager;
|
||||||
|
|
||||||
bool dhcp6_get_prefix_delegation(Link *link);
|
typedef struct DHCP6DelegatedPrefix {
|
||||||
int dhcp6_request_prefix_delegation(Link *link);
|
struct in6_addr prefix; /* Prefix assigned to the 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_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
|
int dhcp6_request_prefix_delegation(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_;
|
||||||
|
|
|
@ -17,7 +17,7 @@ static int ipv4ll_address_lost(Link *link) {
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
link->ipv4ll_address = false;
|
link->ipv4ll_address_configured = 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);
|
assert(!link->ipv4ll_address_configured);
|
||||||
|
|
||||||
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 = true;
|
link->ipv4ll_address_configured = 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 = false;
|
link->ipv4ll_address_configured = 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);
|
r = address_configure(ll_addr, link, ipv4ll_address_handler, false, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -691,7 +691,6 @@ 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);
|
||||||
|
|
||||||
|
@ -699,6 +698,7 @@ 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,17 +711,32 @@ 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_with_destructor(link->routes, route_free);
|
link->routes = set_free(link->routes);
|
||||||
link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
|
link->routes_foreign = set_free(link->routes_foreign);
|
||||||
|
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_with_destructor(link->nexthops, nexthop_free);
|
link->nexthops = set_free(link->nexthops);
|
||||||
link->nexthops_foreign = set_free_with_destructor(link->nexthops_foreign, nexthop_free);
|
link->nexthops_foreign = set_free(link->nexthops_foreign);
|
||||||
|
|
||||||
link->neighbors = set_free_with_destructor(link->neighbors, neighbor_free);
|
link->neighbors = set_free(link->neighbors);
|
||||||
link->neighbors_foreign = set_free_with_destructor(link->neighbors_foreign, neighbor_free);
|
link->neighbors_foreign = set_free(link->neighbors_foreign);
|
||||||
|
|
||||||
link->addresses = set_free_with_destructor(link->addresses, address_free);
|
link->addresses = set_free(link->addresses);
|
||||||
link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
|
link->addresses_foreign = set_free(link->addresses_foreign);
|
||||||
|
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);
|
||||||
|
@ -834,6 +849,12 @@ 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)
|
||||||
|
@ -1037,12 +1058,13 @@ 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. */
|
||||||
|
@ -1061,7 +1083,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);
|
r = route_configure(rt, link, route_handler, NULL);
|
||||||
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)
|
||||||
|
@ -1082,12 +1104,14 @@ 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 (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
|
if (link->state == LINK_STATE_CONFIGURED)
|
||||||
log_link_debug(link, "%s(): link is in failed or linger state.", __func__);
|
return;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,15 +1137,6 @@ 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;
|
||||||
|
@ -1149,7 +1164,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) {
|
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) {
|
||||||
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
|
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1160,17 +1175,19 @@ void link_check_ready(Link *link) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && set_isempty(link->addresses)) {
|
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
|
||||||
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no address is assigned yet.", __func__);
|
!link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) &&
|
||||||
|
!(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) || dhcp6_get_prefix_delegation(link) || link_ipv6_accept_ra_enabled(link)) {
|
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(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)) {
|
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) {
|
||||||
/* 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__);
|
||||||
|
@ -1189,8 +1206,7 @@ void link_check_ready(Link *link) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->state != LINK_STATE_CONFIGURED)
|
link_enter_configured(link);
|
||||||
link_enter_configured(link);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1222,6 +1238,50 @@ 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;
|
||||||
|
|
||||||
|
@ -1247,23 +1307,50 @@ 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 link_set_bridge_fdb(Link *link) {
|
static int static_address_configure(Address *address, Link *link, bool update) {
|
||||||
FdbEntry *fdb_entry;
|
Address *ret;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
|
assert(address);
|
||||||
r = fdb_entry_configure(link, fdb_entry);
|
assert(link);
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
|
r = address_configure(address, link, address_handler, update, &ret);
|
||||||
}
|
if (r < 0)
|
||||||
|
return log_link_warning_errno(link, r, "Could not configure static address: %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;
|
||||||
}
|
}
|
||||||
|
@ -1302,16 +1389,12 @@ 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 = address_configure(ad, link, address_handler, update);
|
r = static_address_configure(ad, link, update);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_warning_errno(link, r, "Could not set addresses: %m");
|
return r;
|
||||||
if (r > 0)
|
|
||||||
link->address_messages++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IN_SET(link->network->router_prefix_delegation,
|
if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC)
|
||||||
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;
|
||||||
|
|
||||||
|
@ -1320,22 +1403,20 @@ static int link_request_set_addresses(Link *link) {
|
||||||
|
|
||||||
r = address_new(&address);
|
r = address_new(&address);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not allocate address: %m");
|
return log_oom();
|
||||||
|
|
||||||
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 r;
|
return log_link_warning_errno(link, r, "Could not get RA prefix: %m");
|
||||||
|
|
||||||
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 r;
|
return log_link_warning_errno(link, r, "Could not generate EUI64 address: %m");
|
||||||
|
|
||||||
address->family = AF_INET6;
|
address->family = AF_INET6;
|
||||||
r = address_configure(address, link, address_handler, true);
|
r = static_address_configure(address, link, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_warning_errno(link, r, "Could not set addresses: %m");
|
return r;
|
||||||
if (r > 0)
|
|
||||||
link->address_messages++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOREACH(labels, label, link->network->address_labels) {
|
LIST_FOREACH(labels, label, link->network->address_labels) {
|
||||||
|
@ -1346,8 +1427,7 @@ 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,
|
/* now that we can figure out a default address for the dhcp server, start it */
|
||||||
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)
|
||||||
|
@ -1357,7 +1437,10 @@ 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_check_ready(link);
|
link->addresses_ready = true;
|
||||||
|
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);
|
||||||
|
@ -1612,12 +1695,14 @@ static int link_acquire_ipv6_conf(Link *link) {
|
||||||
|
|
||||||
r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
|
r = dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
|
||||||
if (r < 0 && r != -EBUSY)
|
if (r < 0 && r != -EBUSY)
|
||||||
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
|
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
|
||||||
else
|
else
|
||||||
log_link_debug(link, "Acquiring DHCPv6 lease");
|
log_link_debug(link, "Acquiring DHCPv6 lease");
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) dhcp6_request_prefix_delegation(link);
|
r = 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;
|
||||||
}
|
}
|
||||||
|
@ -4235,7 +4320,6 @@ 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",
|
||||||
|
@ -4247,12 +4331,6 @@ 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);
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
@ -4269,7 +4347,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,
|
||||||
dhcp6_lease,
|
link->dhcp6_lease,
|
||||||
link->network->dhcp6_use_dns,
|
link->network->dhcp6_use_dns,
|
||||||
sd_dhcp6_lease_get_dns,
|
sd_dhcp6_lease_get_dns,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -4293,7 +4371,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,
|
||||||
dhcp6_lease,
|
link->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);
|
||||||
|
@ -4312,8 +4390,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 (dhcp6_lease)
|
if (link->dhcp6_lease)
|
||||||
(void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
|
(void) sd_dhcp6_lease_get_domains(link->dhcp6_lease, &dhcp6_domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("DOMAINS=", f);
|
fputs("DOMAINS=", f);
|
||||||
|
|
|
@ -87,6 +87,7 @@ 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;
|
||||||
|
@ -95,32 +96,20 @@ typedef struct Link {
|
||||||
Set *nexthops_foreign;
|
Set *nexthops_foreign;
|
||||||
|
|
||||||
sd_dhcp_client *dhcp_client;
|
sd_dhcp_client *dhcp_client;
|
||||||
sd_dhcp_lease *dhcp_lease, *dhcp_lease_old;
|
sd_dhcp_lease *dhcp_lease;
|
||||||
Set *dhcp_routes;
|
Address *dhcp_address, *dhcp_address_old;
|
||||||
|
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:1;
|
bool ipv4ll_address_configured:1;
|
||||||
|
|
||||||
bool addresses_configured:1;
|
bool addresses_configured:1;
|
||||||
bool addresses_ready:1;
|
bool addresses_ready:1;
|
||||||
|
@ -141,10 +130,30 @@ 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;
|
||||||
|
|
|
@ -857,8 +857,10 @@ 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. */
|
/* address_update() logs internally, so we don't need to here. */
|
||||||
(void) address_update(address, flags, scope, &cinfo);
|
r = address_update(address, flags, scope, &cinfo);
|
||||||
|
if (r < 0)
|
||||||
|
link_enter_failed(link);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1821,27 +1823,20 @@ 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);
|
||||||
|
|
||||||
while ((a = hashmap_first_key(m->dhcp6_prefixes)))
|
HASHMAP_FOREACH(link, m->links, i)
|
||||||
(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);
|
||||||
|
|
||||||
link_unref(link);
|
m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
|
||||||
}
|
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);
|
||||||
|
@ -1857,9 +1852,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_with_destructor(m->rules, routing_policy_rule_free);
|
m->rules = set_free(m->rules);
|
||||||
m->rules_foreign = set_free_with_destructor(m->rules_foreign, routing_policy_rule_free);
|
m->rules_foreign = set_free(m->rules_foreign);
|
||||||
set_free_with_destructor(m->rules_saved, routing_policy_rule_free);
|
set_free(m->rules_saved);
|
||||||
|
|
||||||
sd_netlink_unref(m->rtnl);
|
sd_netlink_unref(m->rtnl);
|
||||||
sd_netlink_unref(m->genl);
|
sd_netlink_unref(m->genl);
|
||||||
|
|
|
@ -44,6 +44,7 @@ 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;
|
||||||
|
|
|
@ -35,6 +35,79 @@
|
||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
|
@ -56,6 +129,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +164,13 @@ 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);
|
||||||
|
@ -94,6 +181,50 @@ 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;
|
||||||
|
@ -155,11 +286,9 @@ 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 = route_configure(route, link, ndisc_route_handler);
|
r = ndisc_route_configure(route, link);
|
||||||
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) {
|
||||||
|
@ -171,11 +300,9 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||||
|
|
||||||
route_gw->gw = gateway;
|
route_gw->gw = gateway;
|
||||||
|
|
||||||
r = route_configure(route_gw, link, ndisc_route_handler);
|
r = ndisc_route_configure(route_gw, link);
|
||||||
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;
|
||||||
|
@ -387,11 +514,9 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
|
||||||
|
|
||||||
address->in_addr.in6 = *a;
|
address->in_addr.in6 = *a;
|
||||||
|
|
||||||
r = address_configure(address, link, ndisc_address_handler, true);
|
r = ndisc_address_configure(address, link);
|
||||||
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;
|
||||||
|
@ -435,11 +560,9 @@ 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 = route_configure(route, link, ndisc_route_handler);
|
r = ndisc_route_configure(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");;
|
||||||
if (r > 0)
|
|
||||||
link->ndisc_routes_messages++;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -494,11 +617,9 @@ 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 = route_configure(route, link, ndisc_route_handler);
|
r = ndisc_route_configure(route, link);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -511,12 +632,19 @@ 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(ndisc_rdnss_hash_ops, NDiscRDNSS, ndisc_rdnss_hash_func, ndisc_rdnss_compare_func);
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
|
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);
|
||||||
|
@ -534,28 +662,27 @@ 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");
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
SET_FOREACH(rdnss, link->ndisc_rdnss, 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[i],
|
.address = a[j],
|
||||||
}, *y;
|
};
|
||||||
|
|
||||||
if (lifetime == 0) {
|
rdnss = set_get(link->ndisc_rdnss, &d);
|
||||||
(void) set_remove(link->ndisc_rdnss, &d);
|
if (rdnss) {
|
||||||
link_dirty(link);
|
rdnss->marked = false;
|
||||||
continue;
|
rdnss->valid_until = time_now + lifetime * USEC_PER_SEC;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +691,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[i],
|
.address = a[j],
|
||||||
.valid_until = time_now + lifetime * USEC_PER_SEC,
|
.valid_until = time_now + lifetime * USEC_PER_SEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -572,8 +699,6 @@ 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;
|
||||||
|
@ -587,13 +712,20 @@ 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(ndisc_dnssl_hash_ops, NDiscDNSSL, ndisc_dnssl_hash_func, ndisc_dnssl_compare_func);
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
|
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;
|
||||||
char **i;
|
NDiscDNSSL *dnssl;
|
||||||
|
Iterator i;
|
||||||
|
char **j;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
@ -611,32 +743,31 @@ 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");
|
||||||
|
|
||||||
STRV_FOREACH(i, l) {
|
SET_FOREACH(dnssl, link->ndisc_dnssl, i)
|
||||||
_cleanup_free_ NDiscDNSSL *s = NULL;
|
dnssl->marked = true;
|
||||||
NDiscDNSSL *x;
|
|
||||||
|
|
||||||
s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1);
|
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;
|
||||||
|
|
||||||
|
s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1);
|
||||||
if (!s)
|
if (!s)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
strcpy(NDISC_DNSSL_DOMAIN(s), *i);
|
strcpy(NDISC_DNSSL_DOMAIN(s), *j);
|
||||||
|
|
||||||
if (lifetime == 0) {
|
dnssl = set_get(link->ndisc_dnssl, s);
|
||||||
(void) set_remove(link->ndisc_dnssl, s);
|
if (dnssl) {
|
||||||
link_dirty(link);
|
dnssl->marked = false;
|
||||||
continue;
|
dnssl->valid_until = time_now + lifetime * USEC_PER_SEC;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,8 +777,6 @@ 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;
|
||||||
|
@ -736,6 +865,8 @@ 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;
|
||||||
|
|
||||||
|
@ -744,6 +875,23 @@ 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");
|
||||||
|
@ -757,10 +905,8 @@ 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);
|
||||||
|
@ -770,7 +916,33 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return r;
|
if (link->ndisc_addresses_messages == 0)
|
||||||
|
link->ndisc_addresses_configured = true;
|
||||||
|
else {
|
||||||
|
log_link_debug(link, "Setting SLAAC addresses.");
|
||||||
|
|
||||||
|
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
|
||||||
|
* Before they are called, the related flags must be cleared. Otherwise, the link
|
||||||
|
* becomes configured state before routes are configured. */
|
||||||
|
link->static_routes_configured = false;
|
||||||
|
link->static_nexthops_configured = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link->ndisc_routes_messages == 0)
|
||||||
|
link->ndisc_routes_configured = true;
|
||||||
|
else
|
||||||
|
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)
|
||||||
|
link_check_ready(link);
|
||||||
|
else
|
||||||
|
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) {
|
static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
|
||||||
|
@ -785,44 +957,20 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *r
|
||||||
switch (event) {
|
switch (event) {
|
||||||
|
|
||||||
case SD_NDISC_EVENT_ROUTER:
|
case SD_NDISC_EVENT_ROUTER:
|
||||||
link->ndisc_addresses_configured = false;
|
|
||||||
link->ndisc_routes_configured = false;
|
|
||||||
|
|
||||||
r = ndisc_router_handler(link, rt);
|
r = ndisc_router_handler(link, rt);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->ndisc_addresses_messages == 0)
|
|
||||||
link->ndisc_addresses_configured = true;
|
|
||||||
else {
|
|
||||||
log_link_debug(link, "Setting SLAAC addresses.");
|
|
||||||
|
|
||||||
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
|
|
||||||
* Before they are called, the related flags must be cleared. Otherwise, the link
|
|
||||||
* becomes configured state before routes are configured. */
|
|
||||||
link->static_routes_configured = false;
|
|
||||||
link->static_nexthops_configured = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (link->ndisc_routes_messages == 0)
|
|
||||||
link->ndisc_routes_configured = true;
|
|
||||||
else
|
|
||||||
log_link_debug(link, "Setting NDisc routes.");
|
|
||||||
|
|
||||||
if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
|
|
||||||
link_check_ready(link);
|
|
||||||
else
|
|
||||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
|
||||||
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");
|
||||||
link->ndisc_addresses_configured = true;
|
if (link->ndisc_addresses_messages == 0 && link->ndisc_routes_messages == 0) {
|
||||||
link->ndisc_routes_configured = true;
|
link->ndisc_addresses_configured = true;
|
||||||
link_check_ready(link);
|
link->ndisc_routes_configured = true;
|
||||||
|
link_check_ready(link);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert_not_reached("Unknown NDisc event");
|
assert_not_reached("Unknown NDisc event");
|
||||||
|
@ -862,6 +1010,7 @@ 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);
|
||||||
|
|
||||||
|
@ -872,14 +1021,17 @@ 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));
|
||||||
link_dirty(link);
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
link_dirty(link);
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updated)
|
||||||
|
link_dirty(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ndisc_flush(Link *link) {
|
void ndisc_flush(Link *link) {
|
||||||
|
@ -887,8 +1039,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_free(link->ndisc_rdnss);
|
link->ndisc_rdnss = set_free(link->ndisc_rdnss);
|
||||||
link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
|
link->ndisc_dnssl = set_free(link->ndisc_dnssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipv6token_new(IPv6Token **ret) {
|
int ipv6token_new(IPv6Token **ret) {
|
||||||
|
|
|
@ -24,11 +24,15 @@ 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;
|
||||||
|
|
|
@ -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(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func);
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func, neighbor_free);
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -213,8 +213,6 @@ 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)
|
||||||
|
@ -271,7 +269,9 @@ 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)
|
||||||
Network.IPv6PDSubnetId, config_parse_router_prefix_subnet_id, 0, 0
|
DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id, 0, offsetof(Network, dhcp6_pd_subnet_id)
|
||||||
|
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)
|
||||||
|
|
|
@ -420,7 +420,8 @@ 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_assign_prefix = true,
|
.dhcp6_pd_subnet_id = -1,
|
||||||
|
.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,
|
||||||
|
@ -429,7 +430,6 @@ 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,
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,6 @@ 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;
|
||||||
|
@ -198,8 +197,11 @@ 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;
|
|
||||||
union in_addr_union dhcp6_delegation_prefix_token;
|
/* DHCPv6 Prefix Delegation support */
|
||||||
|
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;
|
||||||
|
|
|
@ -650,10 +650,7 @@ int radv_configure(Link *link) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IN_SET(link->network->router_prefix_delegation,
|
if (link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_STATIC) {
|
||||||
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)
|
||||||
|
@ -673,13 +670,12 @@ 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, struct in6_addr *prefix, uint8_t prefix_len,
|
int radv_add_prefix(Link *link, const 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;
|
||||||
|
@ -870,46 +866,3 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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,
|
RADV_PREFIX_DELEGATION_NONE = 0,
|
||||||
RADV_PREFIX_DELEGATION_STATIC,
|
RADV_PREFIX_DELEGATION_STATIC = 1 << 0,
|
||||||
RADV_PREFIX_DELEGATION_DHCP6,
|
RADV_PREFIX_DELEGATION_DHCP6 = 1 << 1,
|
||||||
RADV_PREFIX_DELEGATION_BOTH,
|
RADV_PREFIX_DELEGATION_BOTH = RADV_PREFIX_DELEGATION_STATIC | RADV_PREFIX_DELEGATION_DHCP6,
|
||||||
_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, struct in6_addr *prefix, uint8_t prefix_len,
|
int radv_add_prefix(Link *link, const 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,7 +60,6 @@ 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);
|
||||||
|
|
|
@ -144,6 +144,14 @@ 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);
|
||||||
|
@ -597,7 +605,8 @@ 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;
|
||||||
|
@ -803,6 +812,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret);
|
||||||
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);
|
||||||
|
|
|
@ -227,7 +227,12 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops, RoutingPolicyRule, routing_policy_rule_hash_func, routing_policy_rule_compare_func);
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
|
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) {
|
||||||
|
|
||||||
|
|
|
@ -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_with_destructor(rules, routing_policy_rule_free);
|
set_free(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
|
@ -8,21 +8,27 @@
|
||||||
#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,
|
/* 4MB for contents of regular files, 64k inodes for directories, symbolic links and device specials, using
|
||||||
using large storage array systems as a baseline */
|
* 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
|
|
||||||
PID1 because 16MB of free space is required. */
|
/* 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. */
|
||||||
#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%
|
|
||||||
translates to 1M inodes */
|
/* The limit used for various tmpfs mounts, but not /tmp itself.
|
||||||
|
* 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
|
||||||
|
|
|
@ -125,10 +125,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, result, code);
|
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(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, result, code);
|
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(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, result, code);
|
printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, strnull(result), code);
|
||||||
assert_se(r == code);
|
assert_se(r == code);
|
||||||
assert_se(streq_ptr(unit, result));
|
assert_se(streq_ptr(unit, result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -864,14 +864,17 @@ 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) {
|
||||||
log_info("/* %s */", __func__);
|
int booted = sd_booted(); /* If this is run in build environments such as koji, /dev might be a
|
||||||
|
* 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", false);
|
test_path_is_encrypted_one("/dev", booted > 0 ? false : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
|
@ -79,21 +79,15 @@ 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);
|
||||||
|
|
||||||
ts = now(CLOCK_MONOTONIC);
|
usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
|
assert_se(sd_event_run(m->event, 100 * USEC_PER_MSEC) >= 0);
|
||||||
assert_se(r >= 0);
|
|
||||||
|
|
||||||
printf("%s: state = %s; result = %s \n",
|
printf("%s: state = %s; result = %s \n",
|
||||||
UNIT(path)->id,
|
UNIT(path)->id,
|
||||||
|
@ -104,8 +98,7 @@ 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));
|
||||||
|
|
||||||
n = now(CLOCK_MONOTONIC);
|
if (now(CLOCK_MONOTONIC) >= end) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#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"
|
||||||
|
@ -84,7 +85,9 @@ static void test_sleep(void) {
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
log_info("/= configuration =/");
|
printf("Secure boot: %sd\n", enable_disable(is_efi_secure_boot()));
|
||||||
|
|
||||||
|
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));
|
||||||
|
@ -94,7 +97,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("/= running system =/");
|
log_info("/= high-level sleep verbs =/");
|
||||||
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");
|
||||||
|
|
|
@ -130,10 +130,12 @@ SendOption=
|
||||||
RequestOptions=
|
RequestOptions=
|
||||||
UserClass=
|
UserClass=
|
||||||
VendorClass=
|
VendorClass=
|
||||||
AssignAcquiredDelegatedPrefixAddress=
|
|
||||||
AssignAcquiredDelegatedPrefixToken=
|
|
||||||
SendVendorOption=
|
SendVendorOption=
|
||||||
RouteMetric=
|
RouteMetric=
|
||||||
|
[DHCPv6PrefixDelegation]
|
||||||
|
SubnetId=
|
||||||
|
Assign=
|
||||||
|
Token=
|
||||||
[Route]
|
[Route]
|
||||||
Destination=
|
Destination=
|
||||||
Protocol=
|
Protocol=
|
||||||
|
@ -203,7 +205,6 @@ NTP=
|
||||||
DHCP=
|
DHCP=
|
||||||
Domains=
|
Domains=
|
||||||
IPv6PrefixDelegation=
|
IPv6PrefixDelegation=
|
||||||
IPv6PDSubnetId=
|
|
||||||
VLAN=
|
VLAN=
|
||||||
DHCPServer=
|
DHCPServer=
|
||||||
BindCarrier=
|
BindCarrier=
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
[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
|
|
@ -0,0 +1,25 @@
|
||||||
|
[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
|
|
@ -1717,6 +1717,8 @@ 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',
|
||||||
|
@ -1729,6 +1731,7 @@ 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']
|
||||||
|
@ -1815,6 +1818,77 @@ 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()
|
||||||
|
|
|
@ -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=10%,nr_inodes=400k
|
Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=400k
|
||||||
|
|
Loading…
Reference in New Issue