]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-radv: refuse packet from the same interface
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 16 Apr 2024 07:23:36 +0000 (16:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 18 Apr 2024 00:40:23 +0000 (09:40 +0900)
Prompted by https://github.com/systemd/systemd/pull/32267#discussion_r1566721306.

src/libsystemd-network/radv-internal.h
src/libsystemd-network/sd-radv.c
src/network/networkd-radv.c
src/systemd/sd-radv.h

index 8091a5d882b09fa9ef3ce671bf3e138470fd0668..d2ec912d496cc7d6db025bb82c32a33ff55688eb 100644 (file)
@@ -98,6 +98,7 @@ struct sd_radv {
 
         int ifindex;
         char *ifname;
+        struct in6_addr ipv6ll;
 
         sd_event *event;
         int event_priority;
index 79210f9e2ca182352ac6ac0a1e52b6e1290604bf..62b69e633ff608570d530bea3a4fbf12c88f4e7d 100644 (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);
 
index b137b9384f7f56746d0a56d5ae1feebd00bb1525..4291165a913c26d38091f1b4bb372ae648fef388 100644 (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);
 }
index 79cbb8975161eb9a09ed61a89bf696fe844097e5..6d17dcc7f6d82dd81d29032e15d874209c71e8eb 100644 (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);