From: Yu Watanabe Date: Fri, 23 Feb 2024 06:41:06 +0000 (+0900) Subject: sd-radv: use ICMP6Packet and sd_ndisc_router_solicit X-Git-Tag: v256-rc1~179^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F32267%2Fhead;p=thirdparty%2Fsystemd.git sd-radv: use ICMP6Packet and sd_ndisc_router_solicit Then, sd-radv can reject invalid Router Solicit messages, e.g. that have invalid options. No effective functional change, just refactoring. --- diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 316fcf1d2bf..79210f9e2ca 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -19,6 +19,7 @@ #include "iovec-util.h" #include "macro.h" #include "memory-util.h" +#include "ndisc-router-solicit-internal.h" #include "network-common.h" #include "radv-internal.h" #include "random-util.h" @@ -237,64 +238,51 @@ static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t life return 0; } -static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - sd_radv *ra = ASSERT_PTR(userdata); - struct in6_addr src; - triple_timestamp timestamp; +static int radv_process_packet(sd_radv *ra, ICMP6Packet *packet) { int r; - assert(s); - assert(ra->event); + assert(ra); + assert(packet); - ssize_t buflen = next_datagram_size_fd(fd); - if (ERRNO_IS_NEG_TRANSIENT(buflen) || ERRNO_IS_NEG_DISCONNECT(buflen)) - return 0; - if (buflen < 0) { - log_radv_errno(ra, buflen, "Failed to determine datagram size to read, ignoring: %m"); - return 0; - } + if (icmp6_packet_get_type(packet) != ND_ROUTER_SOLICIT) + return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG), "Received ICMP6 packet with unexpected type, ignoring."); - _cleanup_free_ char *buf = new0(char, buflen); - if (!buf) - return -ENOMEM; + _cleanup_(sd_ndisc_router_solicit_unrefp) sd_ndisc_router_solicit *rs = NULL; + rs = ndisc_router_solicit_new(packet); + if (!rs) + return log_oom_debug(); - r = icmp6_receive(fd, buf, buflen, &src, ×tamp); - if (ERRNO_IS_NEG_TRANSIENT(r) || ERRNO_IS_NEG_DISCONNECT(r)) - return 0; + r = ndisc_router_solicit_parse(ra, rs); if (r < 0) - switch (r) { - case -EADDRNOTAVAIL: - log_radv(ra, "Received RS from neither link-local nor null address, ignoring."); - return 0; + return r; - case -EMULTIHOP: - log_radv(ra, "Received RS with invalid hop limit, ignoring."); - return 0; + struct in6_addr src = {}; + r = sd_ndisc_router_solicit_get_sender_address(rs, &src); + if (r < 0 && r != -ENODATA) /* null address is allowed */ + return log_radv_errno(ra, r, "Failed to get sender address of RS, ignoring: %m"); - case -EPFNOSUPPORT: - log_radv(ra, "Received invalid source address from ICMPv6 socket, ignoring."); - return 0; + r = radv_send_router(ra, &src, ra->lifetime_usec); + if (r < 0) + return log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", IN6_ADDR_TO_STRING(&src)); - default: - log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, ignoring: %m"); - return 0; - } + log_radv(ra, "Sent solicited Router Advertisement to %s.", IN6_ADDR_TO_STRING(&src)); + return 0; +} - if ((size_t) buflen < sizeof(struct nd_router_solicit)) { - log_radv(ra, "Too short packet received, ignoring"); - return 0; - } +static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL; + sd_radv *ra = ASSERT_PTR(userdata); + int r; - /* TODO: if the sender address is null, check that the message does not have the source link-layer - * address option. See RFC 4861 Section 6.1.1. */ + assert(fd >= 0); - const char *addr = IN6_ADDR_TO_STRING(&src); - r = radv_send_router(ra, &src, ra->lifetime_usec); - if (r < 0) - log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", addr); - else - log_radv(ra, "Sent solicited Router Advertisement to %s.", addr); + r = icmp6_packet_receive(fd, &packet); + if (r < 0) { + log_radv_errno(ra, r, "Failed to receive ICMPv6 packet, ignoring: %m"); + return 0; + } + (void) radv_process_packet(ra, packet); return 0; }