From: Yu Watanabe Date: Tue, 16 Apr 2024 07:23:36 +0000 (+0900) Subject: sd-radv: refuse packet from the same interface X-Git-Tag: v256-rc1~125^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50ba4e401aa00e30e3f7261360f11e7ff7c0c73e;p=thirdparty%2Fsystemd.git sd-radv: refuse packet from the same interface Prompted by https://github.com/systemd/systemd/pull/32267#discussion_r1566721306. --- diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h index 8091a5d882b..d2ec912d496 100644 --- a/src/libsystemd-network/radv-internal.h +++ b/src/libsystemd-network/radv-internal.h @@ -98,6 +98,7 @@ struct sd_radv { int ifindex; char *ifname; + struct in6_addr ipv6ll; sd_event *event; int event_priority; diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index 79210f9e2ca..62b69e633ff 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -260,6 +260,10 @@ static int radv_process_packet(sd_radv *ra, ICMP6Packet *packet) { 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"); + if (r >= 0 && in6_addr_equal(&src, &ra->ipv6ll)) + /* This should be definitely caused by a misconfiguration. If we send RA to ourself, the + * kernel complains about that. Let's ignore the packet. */ + return log_radv_errno(ra, SYNTHETIC_ERRNO(EADDRINUSE), "Received RS from the same interface, ignoring."); r = radv_send_router(ra, &src, ra->lifetime_usec); if (r < 0) @@ -472,6 +476,18 @@ int sd_radv_get_ifname(sd_radv *ra, const char **ret) { return 0; } +int sd_radv_set_link_local_address(sd_radv *ra, const struct in6_addr *addr) { + assert_return(ra, -EINVAL); + assert_return(!addr || in6_addr_is_link_local(addr), -EINVAL); + + if (addr) + ra->ipv6ll = *addr; + else + zero(ra->ipv6ll); + + return 0; +} + int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) { assert_return(ra, -EINVAL); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index b137b9384f7..4291165a913 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -769,6 +769,10 @@ int radv_start(Link *link) { return log_link_debug_errno(link, r, "Failed to request DHCP delegated subnet prefix: %m"); } + r = sd_radv_set_link_local_address(link->radv, &link->ipv6ll_address); + if (r < 0) + return r; + log_link_debug(link, "Starting IPv6 Router Advertisements"); return sd_radv_start(link->radv); } diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 79cbb897516..6d17dcc7f6d 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -52,6 +52,7 @@ int sd_radv_is_running(sd_radv *ra); int sd_radv_set_ifindex(sd_radv *ra, int interface_index); int sd_radv_set_ifname(sd_radv *ra, const char *interface_name); int sd_radv_get_ifname(sd_radv *ra, const char **ret); +int sd_radv_set_link_local_address(sd_radv *ra, const struct in6_addr *addr); int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr); int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu); int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit);