From ab8a8a4e7721270196f9c7984223fcff41754780 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 9 Dec 2021 04:30:54 +0900 Subject: [PATCH] libsystemd-network: ignore -ENETDOWN or friends in recv() And this makes most errors in io events ignored. --- src/libsystemd-network/sd-dhcp-client.c | 41 +++++++++++++----------- src/libsystemd-network/sd-dhcp-server.c | 19 +++++++---- src/libsystemd-network/sd-dhcp6-client.c | 18 +++++------ src/libsystemd-network/sd-ipv4acd.c | 2 +- src/libsystemd-network/sd-lldp-rx.c | 5 ++- src/libsystemd-network/sd-ndisc.c | 17 +++++----- src/libsystemd-network/sd-radv.c | 17 ++++++---- 7 files changed, 70 insertions(+), 49 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 14cbde133f..16574d28c7 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1930,13 +1930,13 @@ static int client_receive_message_udp( assert(client); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event - source will be disconnected and we won't be able to receive - packets again when the link comes back. */ + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } message = malloc0(buflen); if (!message) @@ -1944,12 +1944,11 @@ static int client_receive_message_udp( len = recv(fd, message, buflen, 0); if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (ERRNO_IS_TRANSIENT(errno) || errno == ENETDOWN) + if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) return 0; - return log_dhcp_client_errno(client, errno, - "Could not receive message from UDP socket: %m"); + log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m"); + return 0; } if ((size_t) len < sizeof(DHCPMessage)) { 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 client_handle_message(client, message, len); + (void) client_handle_message(client, message, len); + return 0; } static int client_receive_message_raw( @@ -2023,10 +2023,13 @@ static int client_receive_message_raw( assert(client); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } packet = malloc0(buflen); if (!packet) @@ -2036,10 +2039,11 @@ static int client_receive_message_raw( len = recvmsg_safe(fd, &msg, 0); if (len < 0) { - if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN) + if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len)) return 0; - return log_dhcp_client_errno(client, len, - "Could not receive message from raw socket: %m"); + + log_dhcp_client_errno(client, len, "Could not receive message from raw socket, ignoring: %m"); + return 0; } if ((size_t) len < sizeof(DHCPPacket)) return 0; @@ -2056,7 +2060,8 @@ static int client_receive_message_raw( 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) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index f535e316f9..ea98060ea2 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1191,8 +1191,13 @@ static int server_receive_message(sd_event_source *s, int fd, assert(server); datagram_size = next_datagram_size_fd(fd); - if (datagram_size < 0) - return datagram_size; + if (datagram_size < 0) { + 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; 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); if (len < 0) { - if (ERRNO_IS_TRANSIENT(len)) + if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len)) return 0; - return len; + + log_dhcp_server_errno(server, len, "Could not receive message, ignoring: %m"); + return 0; } 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)) { r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen); 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 { r = dhcp_server_handle_message(server, message, (size_t) len); 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; } diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 29c8f78a8f..d3c667974d 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1463,12 +1463,13 @@ static int client_receive_message( assert(client->event); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event source will be disconnected - * and we won't be able to receive packets again when the link comes back. */ + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp6_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } message = malloc(buflen); if (!message) @@ -1478,12 +1479,11 @@ static int client_receive_message( len = recvmsg_safe(fd, &msg, MSG_DONTWAIT); if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (ERRNO_IS_TRANSIENT(len) || len == -ENETDOWN) + if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len)) 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)) { log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index 9b35d2c48e..232b3b0333 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -362,7 +362,7 @@ static int ipv4acd_on_packet( n = recv(fd, &packet, sizeof(struct ether_arp), 0); if (n < 0) { - if (ERRNO_IS_TRANSIENT(errno)) + if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) return 0; log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); diff --git a/src/libsystemd-network/sd-lldp-rx.c b/src/libsystemd-network/sd-lldp-rx.c index 4caed52a98..34bdcb644b 100644 --- a/src/libsystemd-network/sd-lldp-rx.c +++ b/src/libsystemd-network/sd-lldp-rx.c @@ -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); 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"); 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); if (length < 0) { - if (ERRNO_IS_TRANSIENT(errno)) + if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) return 0; log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m"); diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index 424526db98..7e16f51299 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -186,10 +186,8 @@ static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) { assert(rt); r = ndisc_router_parse(nd, rt); - if (r == -EBADMSG) /* Bad packet */ - return 0; if (r < 0) - return 0; + return r; 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", @@ -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); 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"); 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); if (r < 0) { + if (ERRNO_IS_TRANSIENT(r) || ERRNO_IS_DISCONNECT(r)) + return 0; + switch (r) { case -EADDRNOTAVAIL: (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."); break; - case -EAGAIN: /* ignore spurious wakeups */ - break; - default: log_ndisc_errno(nd, r, "Unexpected error while reading from ICMPv6, ignoring: %m"); 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); - - return ndisc_handle_datagram(nd, rt); + (void) ndisc_handle_datagram(nd, rt); + return 0; } static usec_t ndisc_timeout_compute_random(usec_t val) { diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 4f5dbf0090..f8ffb6358f 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -258,8 +258,13 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat assert(ra->event); buflen = next_datagram_size_fd(fd); - if (buflen < 0) - return (int) buflen; + if (buflen < 0) { + 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); 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, ×tamp); if (r < 0) { + if (ERRNO_IS_TRANSIENT(r) || ERRNO_IS_DISCONNECT(r)) + return 0; + switch (r) { case -EADDRNOTAVAIL: (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."); break; - case -EAGAIN: /* ignore spurious wakeups */ - break; - 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; }