Compare commits

...

12 Commits

Author SHA1 Message Date
Elias Probst a0223c308e NEWS: fix typo (`systemd-userdb` > `systemd-userdbd`) 2020-10-24 22:51:00 +09:00
Yu Watanabe 80762cccdc test-network: add a test case for DNSSL in RA
Closes #4590.
2020-10-24 14:08:51 +02:00
Zbigniew Jędrzejewski-Szmek a5258a0cb0
Merge pull request #17430 from yuwata/network-drop-foreign-routes-managed-by-manager
network: drop routes managed by Manager when they are not requested
2020-10-24 13:44:10 +02:00
Dan Streetman 352ab9d740 test: ignore ENOMEDIUM error from sd_pid_get_cgroup()
Ubuntu builds on the Launchpad infrastructure run inside a chroot that does
not have the sysfs cgroup dirs mounted, so this call will return ENOMEDIUM
from cg_unified_cached() during the build-time testing, for example when
building the package in a Launchpad PPA.
2020-10-24 13:34:01 +02:00
Yu Watanabe 377a9545e9 tree-wide: fix typos found by Fossies codespell report 2020-10-24 13:29:31 +02:00
Yu Watanabe 5a8775bb39 Revert "sd-dhcp-client: use asynchronous_close()"
This effectively reverts the commit 22fc2420b2.

The function `asynchronous_close()` confuses valgrind. Before this commit,
valgrind may report the following:

```
HEAP SUMMARY:
    in use at exit: 384 bytes in 1 blocks
  total heap usage: 4,787 allocs, 4,786 frees, 1,379,191 bytes allocated

384 bytes in 1 blocks are possibly lost in loss record 1 of 1
   at 0x483CAE9: calloc (vg_replace_malloc.c:760)
   by 0x401456A: _dl_allocate_tls (in /usr/lib64/ld-2.31.so)
   by 0x4BD212E: pthread_create@@GLIBC_2.2.5 (in /usr/lib64/libpthread-2.31.so)
   by 0x499B662: asynchronous_job (async.c:47)
   by 0x499B7DC: asynchronous_close (async.c:102)
   by 0x4CFA8B: client_initialize (sd-dhcp-client.c:696)
   by 0x4CFC5E: client_stop (sd-dhcp-client.c:725)
   by 0x4D4589: sd_dhcp_client_stop (sd-dhcp-client.c:2134)
   by 0x493C2F: link_stop_clients (networkd-link.c:620)
   by 0x4126DB: manager_free (networkd-manager.c:867)
   by 0x40D193: manager_freep (networkd-manager.h:97)
   by 0x40DAFC: run (networkd.c:20)

LEAK SUMMARY:
   definitely lost: 0 bytes in 0 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 384 bytes in 1 blocks
   still reachable: 0 bytes in 0 blocks
        suppressed: 0 bytes in 0 blocks

For lists of detected and suppressed errors, rerun with: -s
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```
2020-10-24 13:27:37 +02:00
Yu Watanabe 43d4bc9f56 test-network: add tests for routes managed by Manager 2020-10-23 23:07:12 +09:00
Yu Watanabe 1132a714ec network: drop routes managed by Manager when link is removed
Also, foreign routes managed by Manager are dropped in
link_drop_foreign_routes().
2020-10-23 23:07:12 +09:00
Yu Watanabe 5f4d7aa458 network: specify route type in route_remove()
This factors out the common netlink message handling in route_remote()
and route_configure() to route_set_netlink_message().
2020-10-23 23:07:12 +09:00
Yu Watanabe bac319a795 network: link may be NULL 2020-10-23 23:07:12 +09:00
Yu Watanabe b1dc5946e2 network: ignore error in writing proxy_ndp
This partially reverts the commit fd773a11d8.

As, IPv6 may be disabled by kernel.
2020-10-23 23:07:12 +09:00
Yu Watanabe 9b3e49fc00 network: fix typo 2020-10-23 23:07:12 +09:00
18 changed files with 274 additions and 169 deletions

2
NEWS
View File

@ -1254,7 +1254,7 @@ CHANGES WITH 245:
configuration drop-ins are present, no action is taken. configuration drop-ins are present, no action is taken.
* A new component "userdb" has been added, along with a small daemon * A new component "userdb" has been added, along with a small daemon
"systemd-userdb.service" and a client tool "userdbctl". The framework "systemd-userdbd.service" and a client tool "userdbctl". The framework
allows defining rich user and group records in a JSON format, allows defining rich user and group records in a JSON format,
extending on the classic "struct passwd" and "struct group" extending on the classic "struct passwd" and "struct group"
structures. Various components in systemd have been updated to structures. Various components in systemd have been updated to

4
TODO
View File

@ -20,7 +20,7 @@ Janitorial Clean-ups:
Features: Features:
* teach LoadCredential= the ability to load all files from a specfied dir as * teach LoadCredential= the ability to load all files from a specified dir as
individual creds individual creds
* systemd-analyze netif that explains predictable interface (or networkctl) * systemd-analyze netif that explains predictable interface (or networkctl)
@ -49,7 +49,7 @@ Features:
that the kernel does what we otherwise do. that the kernel does what we otherwise do.
* homed: keep an fd to the homedir open at all times, to keep the fs pinned * homed: keep an fd to the homedir open at all times, to keep the fs pinned
(autofs and such) while user is loged in. (autofs and such) while user is logged in.
* nss-systemd: also synthesize shadow records for users/groups * nss-systemd: also synthesize shadow records for users/groups

View File

@ -127,7 +127,7 @@ identifier (The ID field of `/etc/os-release`). Example:
In order to maximize compatibility with file system implementations and In order to maximize compatibility with file system implementations and
restricted boot loader environments, and to minimize conflicting character use restricted boot loader environments, and to minimize conflicting character use
with other progams, file names shall be chosen from a restricted character set: with other programs, file names shall be chosen from a restricted character set:
ASCII upper and lower case characters, digits, "+", "-", "_" and ".". Also, the ASCII upper and lower case characters, digits, "+", "-", "_" and ".". Also, the
file names should have a length of at least one and at most 255 characters file names should have a length of at least one and at most 255 characters
(including file name suffix). (including file name suffix).

View File

@ -87,7 +87,7 @@
pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname> pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname>
or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note
that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be
honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completly honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completely
disable the pager using <option>--no-pager</option> instead.</para></listitem> disable the pager using <option>--no-pager</option> instead.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -124,7 +124,7 @@
<orderedlist> <orderedlist>
<listitem><para>If <filename>/etc/machine-id</filename> does not exist, this is a first boot. During <listitem><para>If <filename>/etc/machine-id</filename> does not exist, this is a first boot. During
early boot, <command>systemd</command> will write <literal>unitialized\n</literal> to this file and overmount early boot, <command>systemd</command> will write <literal>uninitialized\n</literal> to this file and overmount
a temporary file which contains the actual machine ID. Later (after <filename>first-boot-complete.target</filename> a temporary file which contains the actual machine ID. Later (after <filename>first-boot-complete.target</filename>
has been reached), the real machine ID will be written to disk.</para></listitem> has been reached), the real machine ID will be written to disk.</para></listitem>

View File

@ -125,7 +125,7 @@
<varname>luks.uuid=</varname>, the data device will be set to the one specified by <varname>luks.uuid=</varname>, the data device will be set to the one specified by
<varname>rd.luks.data=</varname> or <varname>luks.data=</varname> of the corresponding UUID.</para> <varname>rd.luks.data=</varname> or <varname>luks.data=</varname> of the corresponding UUID.</para>
<para>LUKS data device parameter is usefull for specifying encrypted data devices with detached headers specified in <para>LUKS data device parameter is useful for specifying encrypted data devices with detached headers specified in
<varname>luks.options</varname> entry containing <literal>header=</literal> argument. For example, <varname>luks.options</varname> entry containing <literal>header=</literal> argument. For example,
<varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40 <varname>rd.luks.uuid=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40
<varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/path/to/luks.hdr <varname>rd.luks.options=</varname>b40f1abf-2a53-400a-889a-2eccc27eaa40=header=/path/to/luks.hdr

View File

@ -184,7 +184,7 @@
<para>In case of single-label names, when search domains are defined, the same logic applies, except <para>In case of single-label names, when search domains are defined, the same logic applies, except
that the name is first suffixed by each of the search domains in turn. Note that this search logic that the name is first suffixed by each of the search domains in turn. Note that this search logic
doesn't apply to any names with at least one dot. Also see the discussion about compatiblity with doesn't apply to any names with at least one dot. Also see the discussion about compatibility with
the traditional glibc resolver below.</para></listitem> the traditional glibc resolver below.</para></listitem>
<listitem><para>If a query does not match any configured routing domain (either per-link or global), it <listitem><para>If a query does not match any configured routing domain (either per-link or global), it
@ -232,7 +232,7 @@
<filename>/etc/hosts</filename>.</para></listitem> <filename>/etc/hosts</filename>.</para></listitem>
<listitem><para>Single-label names are not resolved for A and AAAA records using unicast DNS (unless <listitem><para>Single-label names are not resolved for A and AAAA records using unicast DNS (unless
overriden with <varname>ResolveUnicastSingleLabel=</varname>, see overridden with <varname>ResolveUnicastSingleLabel=</varname>, see
<citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>). <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
This is similar to the <option>no-tld-query</option> option being set in This is similar to the <option>no-tld-query</option> option being set in
<citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. <citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.

View File

@ -885,7 +885,7 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<citerefentry><refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum></citerefentry> for <citerefentry><refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details. Defaults to 0022 for system units. For user units the default value is inherited from the details. Defaults to 0022 for system units. For user units the default value is inherited from the
per-user service manager (whose default is in turn inherited from the system service manager, and per-user service manager (whose default is in turn inherited from the system service manager, and
thus typically also is 0022 — unless overriden by a PAM module). In order to change the per-user mask thus typically also is 0022 — unless overridden by a PAM module). In order to change the per-user mask
for all user services, consider setting the <varname>UMask=</varname> setting of the user's for all user services, consider setting the <varname>UMask=</varname> setting of the user's
<filename>user@.service</filename> system service instance. The per-user umask may also be set via <filename>user@.service</filename> system service instance. The per-user umask may also be set via
the <varname>umask</varname> field of a user's <ulink url="https://systemd.io/USER_RECORD">JSON User the <varname>umask</varname> field of a user's <ulink url="https://systemd.io/USER_RECORD">JSON User

View File

@ -362,7 +362,7 @@
<varlistentry> <varlistentry>
<term><constant>v247</constant></term> <term><constant>v247</constant></term>
<listitem><para>If the PCI slot is assocated with PCI bridge and that has multiple child network <listitem><para>If the PCI slot is associated with PCI bridge and that has multiple child network
controllers then all of them might derive the same value of <varname>ID_NET_NAME_SLOT</varname> controllers then all of them might derive the same value of <varname>ID_NET_NAME_SLOT</varname>
property. That could cause naming conflict if the property is selected as a device name. Now, we detect the property. That could cause naming conflict if the property is selected as a device name. Now, we detect the
situation, slot - bridge relation, and we don't produce the <varname>ID_NET_NAME_SLOT</varname> property to situation, slot - bridge relation, and we don't produce the <varname>ID_NET_NAME_SLOT</varname> property to

View File

@ -14,13 +14,13 @@
#include "sd-dhcp-client.h" #include "sd-dhcp-client.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "async.h"
#include "dhcp-identifier.h" #include "dhcp-identifier.h"
#include "dhcp-internal.h" #include "dhcp-internal.h"
#include "dhcp-lease-internal.h" #include "dhcp-lease-internal.h"
#include "dhcp-protocol.h" #include "dhcp-protocol.h"
#include "dns-domain.h" #include "dns-domain.h"
#include "event-util.h" #include "event-util.h"
#include "fd-util.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "io-util.h" #include "io-util.h"
#include "memory-util.h" #include "memory-util.h"
@ -681,7 +681,7 @@ static int client_initialize(sd_dhcp_client *client) {
client->receive_message = sd_event_source_unref(client->receive_message); client->receive_message = sd_event_source_unref(client->receive_message);
client->fd = asynchronous_close(client->fd); client->fd = safe_close(client->fd);
(void) event_source_disable(client->timeout_resend); (void) event_source_disable(client->timeout_resend);
(void) event_source_disable(client->timeout_t1); (void) event_source_disable(client->timeout_t1);
@ -1426,7 +1426,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
assert(client); assert(client);
client->receive_message = sd_event_source_unref(client->receive_message); client->receive_message = sd_event_source_unref(client->receive_message);
client->fd = asynchronous_close(client->fd); client->fd = safe_close(client->fd);
client->state = DHCP_STATE_REBINDING; client->state = DHCP_STATE_REBINDING;
client->attempt = 0; client->attempt = 0;
@ -1783,7 +1783,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
(void) event_source_disable(client->timeout_resend); (void) event_source_disable(client->timeout_resend);
client->receive_message = client->receive_message =
sd_event_source_unref(client->receive_message); sd_event_source_unref(client->receive_message);
client->fd = asynchronous_close(client->fd); client->fd = safe_close(client->fd);
if (IN_SET(client->state, DHCP_STATE_REQUESTING, if (IN_SET(client->state, DHCP_STATE_REQUESTING,
DHCP_STATE_REBOOTING)) DHCP_STATE_REBOOTING))

View File

@ -68,7 +68,7 @@ static void test_login(void) {
r = sd_pid_get_cgroup(0, &cgroup); r = sd_pid_get_cgroup(0, &cgroup);
log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
assert_se(r == 0); assert_se(IN_SET(r, 0, -ENOMEDIUM));
r = sd_uid_get_display(u2, &display_session); r = sd_uid_get_display(u2, &display_session);
log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));

View File

@ -84,7 +84,7 @@ static int ipv6_proxy_ndp_set(Link *link) {
r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v); r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Cannot configure proxy NDP for the interface: %m"); return log_link_warning_errno(link, r, "Cannot configure proxy NDP for the interface, ignoring: %m");
return v; return v;
} }
@ -100,7 +100,7 @@ int link_set_ipv6_proxy_ndp_addresses(Link *link) {
/* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */ /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */
r = ipv6_proxy_ndp_set(link); r = ipv6_proxy_ndp_set(link);
if (r <= 0) if (r <= 0)
return r; return 0;
SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) {
r = ipv6_proxy_ndp_address_configure(link, address); r = ipv6_proxy_ndp_address_configure(link, address);

View File

@ -581,6 +581,110 @@ static int route_add(Manager *manager, Link *link, const Route *in, const Multip
return 0; return 0;
} }
static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) {
unsigned flags;
int r;
assert(route);
assert(req);
/* link may be NULL */
if (in_addr_is_null(route->gw_family, &route->gw) == 0) {
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
} else {
RouteVia rtvia = {
.family = route->gw_family,
.address = route->gw,
};
r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
}
}
if (route->dst_prefixlen > 0) {
r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
}
if (route->src_prefixlen > 0) {
r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set source prefix length: %m");
}
if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
}
r = sd_rtnl_message_route_set_scope(req, route->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
flags = route->flags;
if (route->gateway_onlink >= 0)
SET_FLAG(flags, RTNH_F_ONLINK, route->gateway_onlink);
r = sd_rtnl_message_route_set_flags(req, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if (route->table != RT_TABLE_MAIN) {
if (route->table < 256) {
r = sd_rtnl_message_route_set_table(req, route->table);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route table: %m");
} else {
r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route table: %m");
/* Table attribute to allow more than 256. */
r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
}
}
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
assert(link); /* Those routes must be attached to a specific link */
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
}
r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
return 0;
}
static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
@ -642,66 +746,11 @@ int route_remove(
strna(route_type_to_string(route->type))); strna(route_type_to_string(route->type)));
} }
if (in_addr_is_null(route->gw_family, &route->gw) == 0) { r = route_set_netlink_message(route, req, link);
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); return r;
} else {
RouteVia rtvia = {
.family = route->gw_family,
.address = route->gw,
};
r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia)); r = netlink_call_async(manager->rtnl, NULL, req,
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
}
}
if (route->dst_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
}
if (route->src_prefixlen) {
r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set source prefix length: %m");
}
if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
}
r = sd_rtnl_message_route_set_scope(req, route->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
assert(link); /* Those routes must be attached to a specific link */
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
}
r = netlink_call_async(link->manager->rtnl, NULL, req,
callback ?: route_remove_handler, callback ?: route_remove_handler,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
@ -712,7 +761,7 @@ int route_remove(
return 0; return 0;
} }
static bool link_is_static_route_configured(const Link *link, const Route *route) { static bool link_has_route(const Link *link, const Route *route) {
Route *net_route; Route *net_route;
assert(link); assert(link);
@ -728,11 +777,78 @@ static bool link_is_static_route_configured(const Link *link, const Route *route
return false; return false;
} }
static bool links_have_route(Manager *manager, const Route *route, const Link *except) {
Link *link;
assert(manager);
HASHMAP_FOREACH(link, manager->links) {
if (link == except)
continue;
if (link_has_route(link, route))
return true;
}
return false;
}
static int manager_drop_foreign_routes(Manager *manager) {
Route *route;
int k, r = 0;
assert(manager);
SET_FOREACH(route, manager->routes_foreign) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
continue;
if (links_have_route(manager, route, NULL))
/* The route will be configured later. */
continue;
/* The existing links do not have the route. Let's drop this now. It may by
* re-configured later. */
k = route_remove(route, manager, NULL, NULL);
if (k < 0 && r >= 0)
r = k;
}
return r;
}
static int manager_drop_routes(Manager *manager, Link *except) {
Route *route;
int k, r = 0;
assert(manager);
SET_FOREACH(route, manager->routes) {
/* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
continue;
if (links_have_route(manager, route, except))
/* The route will be configured later. */
continue;
/* The existing links do not have the route. Let's drop this now. It may by
* re-configured later. */
k = route_remove(route, manager, NULL, NULL);
if (k < 0 && r >= 0)
r = k;
}
return r;
}
int link_drop_foreign_routes(Link *link) { int link_drop_foreign_routes(Link *link) {
Route *route; Route *route;
int k, r = 0; int k, r = 0;
assert(link); assert(link);
assert(link->manager);
SET_FOREACH(route, link->routes_foreign) { SET_FOREACH(route, link->routes_foreign) {
/* do not touch routes managed by the kernel */ /* do not touch routes managed by the kernel */
@ -756,7 +872,7 @@ int link_drop_foreign_routes(Link *link) {
FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
continue; continue;
if (link_is_static_route_configured(link, route)) if (link_has_route(link, route))
k = route_add(NULL, link, route, NULL, NULL); k = route_add(NULL, link, route, NULL, NULL);
else else
k = route_remove(route, NULL, link, NULL); k = route_remove(route, NULL, link, NULL);
@ -764,6 +880,10 @@ int link_drop_foreign_routes(Link *link) {
r = k; r = k;
} }
k = manager_drop_foreign_routes(link->manager);
if (k < 0 && r >= 0)
r = k;
return r; return r;
} }
@ -783,6 +903,10 @@ int link_drop_routes(Link *link) {
r = k; r = k;
} }
k = manager_drop_routes(link->manager, link);
if (k < 0 && r >= 0)
r = k;
return r; return r;
} }
@ -930,7 +1054,6 @@ int route_configure(
Route **ret) { Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
unsigned flags;
int r; int r;
assert(link); assert(link);
@ -974,85 +1097,9 @@ int route_configure(
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m"); return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
if (in_addr_is_null(route->gw_family, &route->gw) == 0) { r = route_set_netlink_message(route, req, link);
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); return r;
} else {
RouteVia rtvia = {
.family = route->gw_family,
.address = route->gw,
};
r = sd_netlink_message_append_data(req, RTA_VIA, &rtvia, sizeof(rtvia));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_VIA attribute: %m");
}
}
if (route->dst_prefixlen > 0) {
r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
}
if (route->src_prefixlen > 0) {
r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
if (r < 0)
return log_link_error_errno(link, r, "Could not set source prefix length: %m");
}
if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
}
r = sd_rtnl_message_route_set_scope(req, route->scope);
if (r < 0)
return log_link_error_errno(link, r, "Could not set scope: %m");
flags = route->flags;
if (route->gateway_onlink >= 0)
SET_FLAG(flags, RTNH_F_ONLINK, route->gateway_onlink);
r = sd_rtnl_message_route_set_flags(req, flags);
if (r < 0)
return log_link_error_errno(link, r, "Could not set flags: %m");
if (route->table != RT_TABLE_MAIN) {
if (route->table < 256) {
r = sd_rtnl_message_route_set_table(req, route->table);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route table: %m");
} else {
r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route table: %m");
/* Table attribute to allow more than 256. */
r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
}
}
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) { if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
r = sd_netlink_message_append_u32(req, RTA_EXPIRES, r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
@ -1061,16 +1108,6 @@ int route_configure(
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m"); return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
} }
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
}
if (route->ttl_propagate >= 0) { if (route->ttl_propagate >= 0) {
r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate); r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
if (r < 0) if (r < 0)

View File

@ -194,7 +194,7 @@ int link_set_sysctl(Link *link) {
r = link_set_ipv6_privacy_extensions(link); r = link_set_ipv6_privacy_extensions(link);
if (r < 0) if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignorign: %m"); log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignoring: %m");
r = link_set_ipv6_accept_ra(link); r = link_set_ipv6_accept_ra(link);
if (r < 0) if (r < 0)

View File

@ -270,7 +270,7 @@ static int attach_empty_file(int loop, int nr) {
* partitions results in immediatey IO errors. There's no pretty way to get rid of them * partitions results in immediatey IO errors. There's no pretty way to get rid of them
* again. Neither LOOP_CLR_FD nor LOOP_CTL_REMOVE suffice (see above). What does work is to * again. Neither LOOP_CLR_FD nor LOOP_CTL_REMOVE suffice (see above). What does work is to
* reassociate them with a new fd however. This is what we do here hence: we associate the devices * reassociate them with a new fd however. This is what we do here hence: we associate the devices
* with an empty file (i.e. an image that definitely has no partitons). We then immediately clear it * with an empty file (i.e. an image that definitely has no partitions). We then immediately clear it
* again. This suffices to make the partitions go away. Ugly but appears to work. */ * again. This suffices to make the partitions go away. Ugly but appears to work. */
log_debug("Found unattached loopback block device /dev/loop%i with partitions. Attaching empty file to remove them.", nr); log_debug("Found unattached loopback block device /dev/loop%i with partitions. Attaching empty file to remove them.", nr);

View File

@ -3,3 +3,6 @@ Name=veth99
[Network] [Network]
IPv6AcceptRA=true IPv6AcceptRA=true
[IPv6AcceptRA]
UseDomains=yes

View File

@ -7,6 +7,7 @@ IPv6SendRA=yes
[IPv6SendRA] [IPv6SendRA]
DNS=_link_local 2002:da8:1:0::1 DNS=_link_local 2002:da8:1:0::1
DNSLifetimeSec=1min DNSLifetimeSec=1min
Domains=hogehoge.test
[IPv6Prefix] [IPv6Prefix]
Prefix=2002:da8:1:0::/64 Prefix=2002:da8:1:0::/64

View File

@ -2230,6 +2230,66 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98') self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98') self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
copy_unit_to_networkd_unit_path('25-address-static.network')
check_output(*networkctl_cmd, 'reload', env=env)
self.wait_online(['dummy98:routable'])
# check all routes managed by Manager are removed
print('### ip route show type blackhole')
output = check_output('ip route show type blackhole')
print(output)
self.assertEqual(output, '')
print('### ip route show type unreachable')
output = check_output('ip route show type unreachable')
print(output)
self.assertEqual(output, '')
print('### ip route show type prohibit')
output = check_output('ip route show type prohibit')
print(output)
self.assertEqual(output, '')
remove_unit_from_networkd_path(['25-address-static.network'])
check_output(*networkctl_cmd, 'reload', env=env)
self.wait_online(['dummy98:routable'])
# check all routes managed by Manager are reconfigured
print('### ip route show type blackhole')
output = check_output('ip route show type blackhole')
print(output)
self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
print('### ip route show type unreachable')
output = check_output('ip route show type unreachable')
print(output)
self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
print('### ip route show type prohibit')
output = check_output('ip route show type prohibit')
print(output)
self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
rc = call("ip link del dummy98")
self.assertEqual(rc, 0)
time.sleep(2)
# check all routes managed by Manager are removed
print('### ip route show type blackhole')
output = check_output('ip route show type blackhole')
print(output)
self.assertEqual(output, '')
print('### ip route show type unreachable')
output = check_output('ip route show type unreachable')
print(output)
self.assertEqual(output, '')
print('### ip route show type prohibit')
output = check_output('ip route show type prohibit')
print(output)
self.assertEqual(output, '')
@expectedFailureIfRTA_VIAIsNotSupported() @expectedFailureIfRTA_VIAIsNotSupported()
def test_route_via_ipv6(self): def test_route_via_ipv6(self):
copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev') copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
@ -3254,6 +3314,10 @@ class NetworkdRATests(unittest.TestCase, Utilities):
self.assertRegex(output, 'fe80::') self.assertRegex(output, 'fe80::')
self.assertRegex(output, '2002:da8:1::1') self.assertRegex(output, '2002:da8:1::1')
output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
print(output)
self.assertIn('hogehoge.test', output)
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
print(output) print(output)
self.assertRegex(output, '2002:da8:1:0') self.assertRegex(output, '2002:da8:1:0')