1
0
mirror of https://github.com/systemd/systemd synced 2026-04-10 17:15:03 +02:00

Compare commits

..

14 Commits

Author SHA1 Message Date
Yu Watanabe
01081e2eab
Merge pull request #21692 from yuwata/network-wireguard-allow-to-start-ndisc-or-radv
network: wireguard: allow to start ndisc or radv
2021-12-09 19:53:58 +09:00
Yu Watanabe
63b7d34716 NEWS: add more entries for v250 2021-12-09 19:40:38 +09:00
Daan De Meyer
6959a051cf NEWS file additions 2021-12-09 11:30:00 +01:00
Zbigniew Jędrzejewski-Szmek
0c62d52fe6
Merge pull request #21691 from yuwata/network-route-prefix-length
network: route: several tiny cleanups
2021-12-09 09:24:36 +01:00
Yu Watanabe
ab8a8a4e77 libsystemd-network: ignore -ENETDOWN or friends in recv()
And this makes most errors in io events ignored.
2021-12-09 09:10:51 +01:00
Yu Watanabe
d2d602f4b4 network: refuse empty or numeric route table names 2021-12-09 09:06:41 +01:00
Yu Watanabe
283f7c9872 doc: fix typo 2021-12-09 08:50:19 +01:00
Yu Watanabe
e096cab2f3 network: wireguard: allow to run NDisc and RADV when IPv6LL address is manually configured
Fixes #17380.
2021-12-09 15:57:47 +09:00
Yu Watanabe
78ef25a5aa network: address: add scope in debugging logs 2021-12-09 15:28:06 +09:00
Yu Watanabe
20228b6d96 network: address: also adjust scope when address is link local address
But again only when Scope= is not explicitly specified.
2021-12-09 15:25:19 +09:00
Yu Watanabe
8f8dc32cc9 network: address: do not adjust user specified scope
This reverts cd1caf30c0bd0d0c6e8df7610c614f52a7345c40.

I cannot remember why such change was made.
At least, the kernel does not refuse to set IPv4 localhost address with
non-host scope, e.g. global.
2021-12-09 15:25:05 +09:00
Yu Watanabe
72fa19239d network: route: mask lower bits of destination or source prefix
Let's gracefully handle user's misconfiguration, e.g.
Destination=192.168.0.1/24
2021-12-09 07:02:59 +09:00
Yu Watanabe
e944711fba network: json: add src address when its prefix length is non-zero
This should not change anything. Just for consistency with
route_set_netlink_message(), which sets RTA_SRC attribute when prefix
length is non-zero.
2021-12-09 07:02:29 +09:00
Yu Watanabe
7cf0ed03f2 network: route: show prefix length of the source in debugging logs
Similar fix to b489d6a26e44d430a997e756ac81767f6e646976.
2021-12-09 06:52:01 +09:00
18 changed files with 225 additions and 97 deletions

103
NEWS
View File

@ -62,6 +62,9 @@ CHANGES WITH 250 in spe:
* The GPT image dissection logic in systemd-nspawn/systemd-dissect/… * The GPT image dissection logic in systemd-nspawn/systemd-dissect/…
now is able to decode images for non-native architectures as well. now is able to decode images for non-native architectures as well.
This enables systemd-nspawn to boot images of non-native
architectures if the corresponding user mode emulator is installed
and systemd-binfmtd is running.
* systemd-logind gained a new settings HandlePowerKeyLongPress=, * systemd-logind gained a new settings HandlePowerKeyLongPress=,
HandleRebootKeyLongPress=, HandleSuspendKeyLongPress= and HandleRebootKeyLongPress=, HandleSuspendKeyLongPress= and
@ -255,6 +258,12 @@ CHANGES WITH 250 in spe:
doesn't accidentally jump too far ahead due to faulty hardware or doesn't accidentally jump too far ahead due to faulty hardware or
batteries. batteries.
* A new setting SaveIntervalSec= has been added to systemd-timesyncd,
which may be used to automatically save the current system time to
disk in regular intervals. This is useful to maintain a roughly
monotonic clock even without RTC hardware and with some robustness
against abnormal system shutdown.
* .network files gained a new UplinkInterface in the [IPv6SendRA] * .network files gained a new UplinkInterface in the [IPv6SendRA]
section, for automatically propagating DNS settings from other section, for automatically propagating DNS settings from other
interfaces. interfaces.
@ -262,26 +271,27 @@ CHANGES WITH 250 in spe:
* The static lease DHCP server logic in systemd-networkd may now serve * The static lease DHCP server logic in systemd-networkd may now serve
IP addresses outside of the configured IP pool range for the server. IP addresses outside of the configured IP pool range for the server.
* A new setting SaveIntervalSec= has been added to systemd-timesyncd,
which may be used to automatically save the current system time to
disk in regular intervals. This is useful to maintain a roughly
monotonic clock even without RTC hardware and with some robustness
against abnormal system shutdown.
* CAN support in systemd-networkd gained four new settings Loopback=, * CAN support in systemd-networkd gained four new settings Loopback=,
OneShot=, PresumeAck=, ClassicDataLengthCode= for tweaking CAN OneShot=, PresumeAck=, ClassicDataLengthCode= for tweaking CAN
control modes. It gained a number of further settings for tweaking control modes. It gained a number of further settings for tweaking
CAN timing quanta. CAN timing quanta.
* The [CAN] section in .network file gained new TimeQuantaNSec=,
PropagationSegment=, PhaseBufferSegment1=, PhaseBufferSegment2=,
SyncJumpWidth=, DataTimeQuantaNSec=, DataPropagationSegment=,
DataPhaseBufferSegment1=, DataPhaseBufferSegment2=, and
DataSyncJumpWidth= settings to control bit-timing processed by the
CAN interface.
* DHCPv4 client support in systemd-networkd learnt a new Label= option * DHCPv4 client support in systemd-networkd learnt a new Label= option
for configuring the address label to apply to configure IPv4 for configuring the address label to apply to configure IPv4
addresses. addresses.
* The various systemd-networkd "ethtool" buffer settings now understand * The various systemd-udevd "ethtool" buffer settings now understand
the special value "max" to configure the buffers to the maximum the the special value "max" to configure the buffers to the maximum the
hardware supports. hardware supports.
* systemd-networkd's .link files may now configure a large variety of * systemd-udevd's .link files may now configure a large variety of
NIC coalescing settings, plus more hardware offload settings. NIC coalescing settings, plus more hardware offload settings.
* systemd-analyze verify gained support for a pair of new --image= + * systemd-analyze verify gained support for a pair of new --image= +
@ -296,18 +306,21 @@ CHANGES WITH 250 in spe:
UseMTU= setting that may be used to control whether to apply the UseMTU= setting that may be used to control whether to apply the
announced MTU settings to the local interface. announced MTU settings to the local interface.
* systemd-networkd now ships with another default .network file: * systemd-networkd now ships with another default .network files:
80-container-vb.network. It matches host-side network bridge device 80-container-vb.network which matches host-side network bridge device
created by systemd-nspawn's --network-bridge or --network-zone created by systemd-nspawn's --network-bridge or --network-zone
switch. switch, and 80-6rd-tunnel.network which matches automatically created
sit tunnel with 6rd prefix when the DHCP 6RD option is received.
* systemd-networkd now supports IP over InfiniBand interfaces. * systemd-networkd and systemd-udevd now support IP over InfiniBand
interfaces.
* systemd-networkd's handling of Endpoint= resolution for WireGuard * systemd-networkd's handling of Endpoint= resolution for WireGuard
interfaces has been improved. interfaces has been improved.
* systemd-networkd will now automatically configure routes to addresses * systemd-networkd will now automatically configure routes to addresses
specified in AllowedIPs=. specified in AllowedIPs=. This feature can be controlled via RouteTable=
and RouteMetric= settings in [WireGuard] or [WireGuardPeer] sections.
* systemd-networkd will now once again automatically generate persistent * systemd-networkd will now once again automatically generate persistent
MAC addresses for batadv and bridge interfaces. Users can disable this MAC addresses for batadv and bridge interfaces. Users can disable this
@ -317,29 +330,56 @@ CHANGES WITH 250 in spe:
section that allows to specify a WoL "SecureOn" password on hardware section that allows to specify a WoL "SecureOn" password on hardware
that supports this. that supports this.
* DHCPv6 Prefix Delegation gained new settings UplinkInterface= and * The [DHCPv4] section in .network file gained a new Use6RD= boolean
UseDelegatedPrefix= for configuring how to propagate delegated setting to control whether the DHCPv4 client request and process the
prefixes between uplink and downlink interfaces. DHCP 6RD option.
* The [DHCPv6PrefixDelegation] section in .network file is renamed to
[DHCPPrefixDelegation], as now the prefix delegation is also supported
with DHCPv4 protocol by enabling the Use6RD= setting.
* The [DHCPPrefixDelegation] section in .network file gained a new
setting UplinkInterface= to specify the upstream interface.
* The [DHCPv6] section in .network file gained a new setting
UseDelegatedPrefix= to control whether the delegated prefixes will be
propagated to the downstream interfaces.
* The [IPv6AcceptRA] section of .network files now understands two new * The [IPv6AcceptRA] section of .network files now understands two new
settings UseGateway=/UseRoutePrefix= for explicitly configuring settings UseGateway=/UseRoutePrefix= for explicitly configuring
whether to use the relevant fields from the IPv6 Router Advertisement whether to use the relevant fields from the IPv6 Router Advertisement
records. records.
* The [CAKE] section of .network files gained a new setting * The ForceDHCPv6PDOtherInformation= setting in the [DHCPv6] section is
AutoRateIngress= for controlling automatic capacity estimation for now deprecated. Please use the WithoutRA= and UseDelegatedPrefix=
CAKE. settings in the [DHCPv6] section and the DHCPv6Client= setting in the
[IPv6AcceptRA] section to control when the DHCPv6 client is started
and how the delegated prefixes are handled by the DHCPv6 client.
* IPv6 tokens configured in .network files may now optionally take a * The [CAKE] section of .network files gained various new settings
secret key (i.e. Token=prefixstable:…) AutoRateIngress=, CompensationMode=, FlowIsolationMode=, NAT=,
MPUBytes=, PriorityQueueingPreset=, FirewallMark=, Wash=, SplitGSO=,
and UseRawPacketSize= for configuring CAKE.
* A new SuppressInterfaceGroup= setting has been added to the * The IPv6Token= section in the [Network] section is deprecated, and
[RoutingPolicyRule] section of .network files. the [IPv6AcceptRA] section gained the Token= setting for its
replacement. The [IPv6Prefix] section also gained the Token= setting.
The Token= setting gained 'eui64' mode to explicitly configure an
address with the EUI64 algorithm based on the interface MAC address.
The 'prefixstable' mode can now optionally take a secret key. The
Token= setting in the [DHCPPrefixDelegation] section now supports all
algorithms supported by the same settings in the other sections.
* The [RoutingPolicyRule] section of .network file gained a new
SuppressInterfaceGroup= setting.
* The IgnoreCarrierLoss= setting in the [Network] section of .network * The IgnoreCarrierLoss= setting in the [Network] section of .network
files now accepts a duration to be specified, controlling how time to files now accepts a duration to be specified, controlling how time to
wait before no longer ignoring carrier losses. wait before no longer ignoring carrier losses.
* The [DHCPServer] section of .network file gained a new Router= setting
to specify the router address.
* systemd-analyze verify gained a new switch --recursive-errors= which * systemd-analyze verify gained a new switch --recursive-errors= which
controls whether to only fail on errors found in the specified units controls whether to only fail on errors found in the specified units
or recursively any dependent units. or recursively any dependent units.
@ -677,6 +717,23 @@ CHANGES WITH 250 in spe:
file that explains the licenses used by source files in this repository. file that explains the licenses used by source files in this repository.
It also contains the text of all applicable licenses as they appear on spdx.org. It also contains the text of all applicable licenses as they appear on spdx.org.
* systemd-journald now re-enables COW for archived journal files on filesystems
that support COW. One benefit of this change is that archived journal files will
now get compressed on btrfs filesystems that have compression enabled.
* systemd-journald now truncates archived journal files and punches holes in unused
parts of archived journal files, leading to some minor reductions in disk usage.
* systemd-journald now deduplicates fields in a single log message before adding
it to the journal.
* journalctl --verify was extended with more informative error messages.
* More of sd-journal's functions are now resistant against journal file corruption.
* systemd-journald's own logging messages are now also logged to the journal itself
when systemd-journald logs to /dev/kmsg.
CHANGES WITH 249: CHANGES WITH 249:
* When operating on disk images via the --image= switch of various * When operating on disk images via the --image= switch of various

View File

@ -10,7 +10,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
1. Add all items to NEWS 1. Add all items to NEWS
2. Update the contributors list in NEWS (`meson compile -C build git-contrib`) 2. Update the contributors list in NEWS (`meson compile -C build git-contrib`)
3. Update the time and place in NEWS 3. Update the time and place in NEWS
4. Update hwb (`meson compile -C build update-hwdb update-hwdb-autosuspend`) 4. Update hwdb (`meson compile -C build update-hwdb update-hwdb-autosuspend`)
5. [RC1] Update version and library numbers in `meson.build` 5. [RC1] Update version and library numbers in `meson.build`
6. Check dbus docs with `meson compile -C build update-dbus-docs` 6. Check dbus docs with `meson compile -C build update-dbus-docs`
7. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"` 7. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"`

View File

@ -1930,13 +1930,13 @@ static int client_receive_message_udp(
assert(client); assert(client);
buflen = next_datagram_size_fd(fd); buflen = next_datagram_size_fd(fd);
if (buflen == -ENETDOWN) if (buflen < 0) {
/* the link is down. Don't return an error or the I/O event if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
source will be disconnected and we won't be able to receive
packets again when the link comes back. */
return 0; return 0;
if (buflen < 0)
return buflen; log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
return 0;
}
message = malloc0(buflen); message = malloc0(buflen);
if (!message) if (!message)
@ -1944,12 +1944,11 @@ static int client_receive_message_udp(
len = recv(fd, message, buflen, 0); len = recv(fd, message, buflen, 0);
if (len < 0) { if (len < 0) {
/* see comment above for why we shouldn't error out on ENETDOWN. */ if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno))
if (ERRNO_IS_TRANSIENT(errno) || errno == ENETDOWN)
return 0; return 0;
return log_dhcp_client_errno(client, errno, log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m");
"Could not receive message from UDP socket: %m"); return 0;
} }
if ((size_t) len < sizeof(DHCPMessage)) { if ((size_t) len < sizeof(DHCPMessage)) {
log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
@ -1995,7 +1994,8 @@ static int client_receive_message_udp(
return 0; return 0;
} }
return client_handle_message(client, message, len); (void) client_handle_message(client, message, len);
return 0;
} }
static int client_receive_message_raw( static int client_receive_message_raw(
@ -2023,10 +2023,13 @@ static int client_receive_message_raw(
assert(client); assert(client);
buflen = next_datagram_size_fd(fd); buflen = next_datagram_size_fd(fd);
if (buflen == -ENETDOWN) if (buflen < 0) {
if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
return 0; return 0;
if (buflen < 0)
return buflen; log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
return 0;
}
packet = malloc0(buflen); packet = malloc0(buflen);
if (!packet) if (!packet)
@ -2036,10 +2039,11 @@ static int client_receive_message_raw(
len = recvmsg_safe(fd, &msg, 0); len = recvmsg_safe(fd, &msg, 0);
if (len < 0) { if (len < 0) {
if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN) if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len))
return 0;
log_dhcp_client_errno(client, len, "Could not receive message from raw socket, ignoring: %m");
return 0; return 0;
return log_dhcp_client_errno(client, len,
"Could not receive message from raw socket: %m");
} }
if ((size_t) len < sizeof(DHCPPacket)) if ((size_t) len < sizeof(DHCPPacket))
return 0; return 0;
@ -2056,7 +2060,8 @@ static int client_receive_message_raw(
len -= DHCP_IP_UDP_SIZE; len -= DHCP_IP_UDP_SIZE;
return client_handle_message(client, &packet->dhcp, len); (void) client_handle_message(client, &packet->dhcp, len);
return 0;
} }
int sd_dhcp_client_send_renew(sd_dhcp_client *client) { int sd_dhcp_client_send_renew(sd_dhcp_client *client) {

View File

@ -1191,8 +1191,13 @@ static int server_receive_message(sd_event_source *s, int fd,
assert(server); assert(server);
datagram_size = next_datagram_size_fd(fd); datagram_size = next_datagram_size_fd(fd);
if (datagram_size < 0) if (datagram_size < 0) {
return datagram_size; if (ERRNO_IS_TRANSIENT(datagram_size) || ERRNO_IS_DISCONNECT(datagram_size))
return 0;
log_dhcp_server_errno(server, datagram_size, "Failed to determine datagram size to read, ignoring: %m");
return 0;
}
size_t buflen = datagram_size; size_t buflen = datagram_size;
if (sd_dhcp_server_is_in_relay_mode(server)) if (sd_dhcp_server_is_in_relay_mode(server))
@ -1207,9 +1212,11 @@ static int server_receive_message(sd_event_source *s, int fd,
len = recvmsg_safe(fd, &msg, 0); len = recvmsg_safe(fd, &msg, 0);
if (len < 0) { if (len < 0) {
if (ERRNO_IS_TRANSIENT(len)) if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len))
return 0;
log_dhcp_server_errno(server, len, "Could not receive message, ignoring: %m");
return 0; return 0;
return len;
} }
if ((size_t) len < sizeof(DHCPMessage)) if ((size_t) len < sizeof(DHCPMessage))
@ -1233,11 +1240,11 @@ static int server_receive_message(sd_event_source *s, int fd,
if (sd_dhcp_server_is_in_relay_mode(server)) { if (sd_dhcp_server_is_in_relay_mode(server)) {
r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen); r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen);
if (r < 0) if (r < 0)
log_dhcp_server_errno(server, r, "Couldn't relay message: %m"); log_dhcp_server_errno(server, r, "Couldn't relay message, ignoring: %m");
} else { } else {
r = dhcp_server_handle_message(server, message, (size_t) len); r = dhcp_server_handle_message(server, message, (size_t) len);
if (r < 0) if (r < 0)
log_dhcp_server_errno(server, r, "Couldn't process incoming message: %m"); log_dhcp_server_errno(server, r, "Couldn't process incoming message, ignoring: %m");
} }
return 0; return 0;
} }

View File

@ -1463,12 +1463,13 @@ static int client_receive_message(
assert(client->event); assert(client->event);
buflen = next_datagram_size_fd(fd); buflen = next_datagram_size_fd(fd);
if (buflen == -ENETDOWN) if (buflen < 0) {
/* the link is down. Don't return an error or the I/O event source will be disconnected if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
* and we won't be able to receive packets again when the link comes back. */
return 0; return 0;
if (buflen < 0)
return buflen; log_dhcp6_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
return 0;
}
message = malloc(buflen); message = malloc(buflen);
if (!message) if (!message)
@ -1478,12 +1479,11 @@ static int client_receive_message(
len = recvmsg_safe(fd, &msg, MSG_DONTWAIT); len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
if (len < 0) { if (len < 0) {
/* see comment above for why we shouldn't error out on ENETDOWN. */ if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len))
if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN)
return 0; return 0;
return log_dhcp6_client_errno(client, len, "Could not receive message from UDP socket: %m"); log_dhcp6_client_errno(client, len, "Could not receive message from UDP socket, ignoring: %m");
return 0;
} }
if ((size_t) len < sizeof(DHCP6Message)) { if ((size_t) len < sizeof(DHCP6Message)) {
log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring");

View File

@ -362,7 +362,7 @@ static int ipv4acd_on_packet(
n = recv(fd, &packet, sizeof(struct ether_arp), 0); n = recv(fd, &packet, sizeof(struct ether_arp), 0);
if (n < 0) { if (n < 0) {
if (ERRNO_IS_TRANSIENT(errno)) if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno))
return 0; return 0;
log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m");

View File

@ -200,6 +200,9 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents
space = next_datagram_size_fd(fd); space = next_datagram_size_fd(fd);
if (space < 0) { if (space < 0) {
if (ERRNO_IS_TRANSIENT(space) || ERRNO_IS_DISCONNECT(space))
return 0;
log_lldp_rx_errno(lldp_rx, space, "Failed to determine datagram size to read, ignoring: %m"); log_lldp_rx_errno(lldp_rx, space, "Failed to determine datagram size to read, ignoring: %m");
return 0; return 0;
} }
@ -212,7 +215,7 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents
length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
if (length < 0) { if (length < 0) {
if (ERRNO_IS_TRANSIENT(errno)) if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno))
return 0; return 0;
log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m"); log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m");

View File

@ -186,10 +186,8 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) {
assert(rt); assert(rt);
r = ndisc_router_parse(nd, rt); r = ndisc_router_parse(nd, rt);
if (r == -EBADMSG) /* Bad packet */
return 0;
if (r < 0) if (r < 0)
return 0; return r;
log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %" PRIu16 " sec", log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %" PRIu16 " sec",
rt->flags & ND_RA_FLAG_MANAGED ? "MANAGED" : rt->flags & ND_RA_FLAG_OTHER ? "OTHER" : "none", rt->flags & ND_RA_FLAG_MANAGED ? "MANAGED" : rt->flags & ND_RA_FLAG_OTHER ? "OTHER" : "none",
@ -213,6 +211,9 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
buflen = next_datagram_size_fd(fd); buflen = next_datagram_size_fd(fd);
if (buflen < 0) { if (buflen < 0) {
if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
return 0;
log_ndisc_errno(nd, buflen, "Failed to determine datagram size to read, ignoring: %m"); log_ndisc_errno(nd, buflen, "Failed to determine datagram size to read, ignoring: %m");
return 0; return 0;
} }
@ -223,6 +224,9 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address, &rt->timestamp); r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address, &rt->timestamp);
if (r < 0) { if (r < 0) {
if (ERRNO_IS_TRANSIENT(r) || ERRNO_IS_DISCONNECT(r))
return 0;
switch (r) { switch (r) {
case -EADDRNOTAVAIL: case -EADDRNOTAVAIL:
(void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &rt->address, &addr); (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &rt->address, &addr);
@ -237,9 +241,6 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
log_ndisc(nd, "Received invalid source address from ICMPv6 socket. Ignoring."); log_ndisc(nd, "Received invalid source address from ICMPv6 socket. Ignoring.");
break; break;
case -EAGAIN: /* ignore spurious wakeups */
break;
default: default:
log_ndisc_errno(nd, r, "Unexpected error while reading from ICMPv6, ignoring: %m"); log_ndisc_errno(nd, r, "Unexpected error while reading from ICMPv6, ignoring: %m");
break; break;
@ -249,8 +250,8 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
} }
(void) event_source_disable(nd->timeout_event_source); (void) event_source_disable(nd->timeout_event_source);
(void) ndisc_handle_datagram(nd, rt);
return ndisc_handle_datagram(nd, rt); return 0;
} }
static usec_t ndisc_timeout_compute_random(usec_t val) { static usec_t ndisc_timeout_compute_random(usec_t val) {

View File

@ -258,8 +258,13 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
assert(ra->event); assert(ra->event);
buflen = next_datagram_size_fd(fd); buflen = next_datagram_size_fd(fd);
if (buflen < 0) if (buflen < 0) {
return (int) buflen; if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
return 0;
log_radv_errno(ra, buflen, "Failed to determine datagram size to read, ignoring: %m");
return 0;
}
buf = new0(char, buflen); buf = new0(char, buflen);
if (!buf) if (!buf)
@ -267,6 +272,9 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
r = icmp6_receive(fd, buf, buflen, &src, &timestamp); r = icmp6_receive(fd, buf, buflen, &src, &timestamp);
if (r < 0) { if (r < 0) {
if (ERRNO_IS_TRANSIENT(r) || ERRNO_IS_DISCONNECT(r))
return 0;
switch (r) { switch (r) {
case -EADDRNOTAVAIL: case -EADDRNOTAVAIL:
(void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &src, &addr); (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &src, &addr);
@ -281,11 +289,8 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
log_radv(ra, "Received invalid source address from ICMPv6 socket. Ignoring."); log_radv(ra, "Received invalid source address from ICMPv6 socket. Ignoring.");
break; break;
case -EAGAIN: /* ignore spurious wakeups */
break;
default: default:
log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, Ignoring: %m"); log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, ignoring: %m");
break; break;
} }

View File

@ -600,7 +600,7 @@ const char* format_lifetime(char *buf, size_t l, usec_t lifetime_usec) {
} }
static void log_address_debug(const Address *address, const char *str, const Link *link) { static void log_address_debug(const Address *address, const char *str, const Link *link) {
_cleanup_free_ char *state = NULL, *addr = NULL, *peer = NULL, *flags_str = NULL; _cleanup_free_ char *state = NULL, *addr = NULL, *peer = NULL, *flags_str = NULL, *scope_str = NULL;
assert(address); assert(address);
assert(str); assert(str);
@ -615,13 +615,14 @@ static void log_address_debug(const Address *address, const char *str, const Lin
(void) in_addr_to_string(address->family, &address->in_addr_peer, &peer); (void) in_addr_to_string(address->family, &address->in_addr_peer, &peer);
(void) address_flags_to_string_alloc(address->flags, address->family, &flags_str); (void) address_flags_to_string_alloc(address->flags, address->family, &flags_str);
(void) route_scope_to_string_alloc(address->scope, &scope_str);
log_link_debug(link, "%s %s address (%s): %s%s%s/%u (valid %s, preferred %s), flags: %s", log_link_debug(link, "%s %s address (%s): %s%s%s/%u (valid %s, preferred %s), flags: %s, scope: %s",
str, strna(network_config_source_to_string(address->source)), strna(state), str, strna(network_config_source_to_string(address->source)), strna(state),
strnull(addr), peer ? " peer " : "", strempty(peer), address->prefixlen, strnull(addr), peer ? " peer " : "", strempty(peer), address->prefixlen,
FORMAT_LIFETIME(address->lifetime_valid_usec), FORMAT_LIFETIME(address->lifetime_valid_usec),
FORMAT_LIFETIME(address->lifetime_preferred_usec), FORMAT_LIFETIME(address->lifetime_preferred_usec),
strna(flags_str)); strna(flags_str), strna(scope_str));
} }
static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) { static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
@ -751,7 +752,7 @@ int link_drop_ipv6ll_addresses(Link *link) {
/* IPv6LL address may be in the tentative state, and in that case networkd has not received it. /* IPv6LL address may be in the tentative state, and in that case networkd has not received it.
* So, we need to dump all IPv6 addresses. */ * So, we need to dump all IPv6 addresses. */
if (link_ipv6ll_enabled(link)) if (link_may_have_ipv6ll(link))
return 0; return 0;
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, link->ifindex, AF_INET6); r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, link->ifindex, AF_INET6);
@ -1916,18 +1917,11 @@ static int address_section_verify(Address *address) {
address->label = mfree(address->label); address->label = mfree(address->label);
} }
if (in_addr_is_localhost(address->family, &address->in_addr) > 0 && if (!address->scope_set) {
(address->family == AF_INET || !address->scope_set)) { if (in_addr_is_localhost(address->family, &address->in_addr) > 0)
/* For IPv4, scope must be always RT_SCOPE_HOST.
* For IPv6, use RT_SCOPE_HOST only when it is not explicitly specified. */
if (address->scope_set && address->scope != RT_SCOPE_HOST)
log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: non-host scope is set for localhost address. "
"Ignoring Scope= setting in the [Address] section from line %u. ",
address->section->filename, address->section->line);
address->scope = RT_SCOPE_HOST; address->scope = RT_SCOPE_HOST;
else if (in_addr_is_link_local(address->family, &address->in_addr) > 0)
address->scope = RT_SCOPE_LINK;
} }
if (address->family == AF_INET6 && if (address->family == AF_INET6 &&

View File

@ -299,9 +299,9 @@ static int route_build_json(Route *route, JsonVariant **ret) {
JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family), JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family),
JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen), JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->gw, route->gw_family), JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->gw, route->gw_family),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Source", &route->src, route->family), JSON_BUILD_PAIR_CONDITION(route->src_prefixlen > 0,
JSON_BUILD_PAIR_CONDITION(in_addr_is_set(route->family, &route->src), "Source", JSON_BUILD_IN_ADDR(&route->src, route->family)),
"SourcePrefixLength", JSON_BUILD_UNSIGNED(route->src_prefixlen)), JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("SourcePrefixLength", route->src_prefixlen),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("PreferredSource", &route->prefsrc, route->family), JSON_BUILD_PAIR_IN_ADDR_NON_NULL("PreferredSource", &route->prefsrc, route->family),
JSON_BUILD_PAIR_UNSIGNED("Scope", route->scope), JSON_BUILD_PAIR_UNSIGNED("Scope", route->scope),
JSON_BUILD_PAIR_STRING("ScopeString", scope), JSON_BUILD_PAIR_STRING("ScopeString", scope),

View File

@ -126,6 +126,43 @@ bool link_ipv6ll_enabled(Link *link) {
return link->network->link_local & ADDRESS_FAMILY_IPV6; return link->network->link_local & ADDRESS_FAMILY_IPV6;
} }
bool link_may_have_ipv6ll(Link *link) {
assert(link);
/*
* This is equivalent to link_ipv6ll_enabled() for non-WireGuard interfaces.
*
* For WireGuard interface, the kernel does not assign any IPv6LL addresses, but we can assign
* it manually. It is necessary to set an IPv6LL address manually to run NDisc or RADV on
* WireGuard interface. Note, also Multicast=yes must be set. See #17380.
*
* TODO: May be better to introduce GenerateIPv6LinkLocalAddress= setting, and use algorithms
* used in networkd-address-generation.c
*/
if (link_ipv6ll_enabled(link))
return true;
/* IPv6LL address can be manually assigned on WireGuard interface. */
if (streq_ptr(link->kind, "wireguard")) {
Address *a;
if (!link->network)
return false;
ORDERED_HASHMAP_FOREACH(a, link->network->addresses_by_section) {
if (a->family != AF_INET6)
continue;
if (in6_addr_is_set(&a->in_addr_peer.in6))
continue;
if (in6_addr_is_link_local(&a->in_addr.in6))
return true;
}
}
return false;
}
bool link_ipv6_enabled(Link *link) { bool link_ipv6_enabled(Link *link) {
assert(link); assert(link);

View File

@ -215,6 +215,7 @@ bool link_has_carrier(Link *link);
bool link_ipv6_enabled(Link *link); bool link_ipv6_enabled(Link *link);
bool link_ipv6ll_enabled(Link *link); bool link_ipv6ll_enabled(Link *link);
bool link_may_have_ipv6ll(Link *link);
int link_ipv6ll_gained(Link *link); int link_ipv6ll_gained(Link *link);
bool link_ipv4ll_enabled(Link *link); bool link_ipv4ll_enabled(Link *link);

View File

@ -37,7 +37,7 @@ bool link_ipv6_accept_ra_enabled(Link *link) {
if (!link->network) if (!link->network)
return false; return false;
if (!link_ipv6ll_enabled(link)) if (!link_may_have_ipv6ll(link))
return false; return false;
assert(link->network->ipv6_accept_ra >= 0); assert(link->network->ipv6_accept_ra >= 0);

View File

@ -54,7 +54,7 @@ void network_adjust_radv(Network *network) {
bool link_radv_enabled(Link *link) { bool link_radv_enabled(Link *link) {
assert(link); assert(link);
if (!link_ipv6ll_enabled(link)) if (!link_may_have_ipv6ll(link))
return false; return false;
return link->network->router_prefix_delegation; return link->network->router_prefix_delegation;

View File

@ -360,9 +360,19 @@ int config_parse_route_table_names(
*num++ = '\0'; *num++ = '\0';
if (isempty(name)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Route table name cannot be empty. Ignoring assignment: %s:%s", name, num);
continue;
}
if (in_charset(name, DIGITS)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Route table name cannot be numeric. Ignoring assignment: %s:%s", name, num);
continue;
}
if (STR_IN_SET(name, "default", "main", "local")) { if (STR_IN_SET(name, "default", "main", "local")) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Route table name %s already predefined. Ignoring assignment: %s:%s", name, name, num); "Route table name %s is already predefined. Ignoring assignment: %s:%s", name, name, num);
continue; continue;
} }

View File

@ -560,8 +560,8 @@ static void log_route_debug(const Route *route, const char *str, const Link *lin
(void) network_config_state_to_string_alloc(route->state, &state); (void) network_config_state_to_string_alloc(route->state, &state);
if (in_addr_is_set(route->family, &route->dst) || route->dst_prefixlen > 0) if (in_addr_is_set(route->family, &route->dst) || route->dst_prefixlen > 0)
(void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst); (void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst);
if (in_addr_is_set(route->family, &route->src)) if (in_addr_is_set(route->family, &route->src) || route->src_prefixlen > 0)
(void) in_addr_to_string(route->family, &route->src, &src); (void) in_addr_prefix_to_string(route->family, &route->src, route->src_prefixlen, &src);
if (in_addr_is_set(route->gw_family, &route->gw)) { if (in_addr_is_set(route->gw_family, &route->gw)) {
(void) in_addr_to_string(route->gw_family, &route->gw, &gw_alloc); (void) in_addr_to_string(route->gw_family, &route->gw, &gw_alloc);
gw = gw_alloc; gw = gw_alloc;
@ -2124,6 +2124,8 @@ int config_parse_destination(
return 0; return 0;
} }
(void) in_addr_mask(n->family, buffer, *prefixlen);
TAKE_PTR(n); TAKE_PTR(n);
return 0; return 0;
} }

View File

@ -146,6 +146,12 @@ static void test_route_tables(Manager *manager) {
assert_se(!manager->route_table_names_by_number); assert_se(!manager->route_table_names_by_number);
assert_se(!manager->route_table_numbers_by_name); assert_se(!manager->route_table_numbers_by_name);
/* Invalid pairs */
assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "main:123 default:333 local:999", manager, manager) >= 0);
assert_se(config_parse_route_table_names("manager", "filename", 1, "section", 1, "RouteTable", 0, "1234:321 :567 hoge:foo aaa:-888", manager, manager) >= 0);
assert_se(!manager->route_table_names_by_number);
assert_se(!manager->route_table_numbers_by_name);
test_route_tables_one(manager, "default", 253); test_route_tables_one(manager, "default", 253);
test_route_tables_one(manager, "main", 254); test_route_tables_one(manager, "main", 254);
test_route_tables_one(manager, "local", 255); test_route_tables_one(manager, "local", 255);