sd-radv: refuse packet from the same interface

Prompted by https://github.com/systemd/systemd/pull/32267#discussion_r1566721306.
This commit is contained in:
Yu Watanabe
2024-04-16 16:23:36 +09:00
parent 258729a3b8
commit 50ba4e401a
4 changed files with 22 additions and 0 deletions

View File

@@ -98,6 +98,7 @@ struct sd_radv {
int ifindex;
char *ifname;
struct in6_addr ipv6ll;
sd_event *event;
int event_priority;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);