Compare commits
12 Commits
e149ba1b1f
...
a0223c308e
Author | SHA1 | Date |
---|---|---|
Elias Probst | a0223c308e | |
Yu Watanabe | 80762cccdc | |
Zbigniew Jędrzejewski-Szmek | a5258a0cb0 | |
Dan Streetman | 352ab9d740 | |
Yu Watanabe | 377a9545e9 | |
Yu Watanabe | 5a8775bb39 | |
Yu Watanabe | 43d4bc9f56 | |
Yu Watanabe | 1132a714ec | |
Yu Watanabe | 5f4d7aa458 | |
Yu Watanabe | bac319a795 | |
Yu Watanabe | b1dc5946e2 | |
Yu Watanabe | 9b3e49fc00 |
2
NEWS
2
NEWS
|
@ -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
4
TODO
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -3,3 +3,6 @@ Name=veth99
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
IPv6AcceptRA=true
|
IPv6AcceptRA=true
|
||||||
|
|
||||||
|
[IPv6AcceptRA]
|
||||||
|
UseDomains=yes
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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')
|
||||||
|
|
Loading…
Reference in New Issue