]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
icmp6-util: make icmp6_receive() accept the null source address
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 4 Sep 2023 08:44:45 +0000 (17:44 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 4 Sep 2023 12:54:43 +0000 (21:54 +0900)
Fixes #29050.

src/libsystemd-network/fuzz-ndisc-rs.c
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/sd-radv.c
src/libsystemd-network/test-ndisc-rs.c

index 5493538fec0ac931b80b99f03cee993eee27e492..ef5567329e4a0c06fce3e1679da2a4790bc4e3e1 100644 (file)
@@ -24,6 +24,13 @@ int icmp6_bind_router_advertisement(int index) {
         return -ENOSYS;
 }
 
+static struct in6_addr dummy_link_local = {
+        .s6_addr = {
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x12, 0x34, 0x56, 0xff, 0xfe, 0x78, 0x9a, 0xbc,
+        },
+};
+
 int icmp6_receive(
                 int fd,
                 void *iov_base,
@@ -36,6 +43,9 @@ int icmp6_receive(
         if (ret_timestamp)
                 triple_timestamp_get(ret_timestamp);
 
+        if (ret_sender)
+                *ret_sender = dummy_link_local;
+
         return 0;
 }
 
index 46318505bae2f69e0c3a0bacaac0403a816282cf..ecd0dd0f3175911a45c24c5e96d4c82f98b5f0d4 100644 (file)
@@ -182,7 +182,7 @@ int icmp6_receive(
             sa.in6.sin6_family == AF_INET6)  {
 
                 addr = sa.in6.sin6_addr;
-                if (!in6_addr_is_link_local(&addr))
+                if (!in6_addr_is_link_local(&addr) && !in6_addr_is_null(&addr))
                         return -EADDRNOTAVAIL;
 
         } else if (msg.msg_namelen > 0)
index 8a6760188d1dca78dbe69af37cccb87cbe6e6e42..d7d9e7e2d9f3299614dad60d89374545efe8130d 100644 (file)
@@ -225,7 +225,7 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
         if (r < 0)
                 switch (r) {
                 case -EADDRNOTAVAIL:
-                        log_ndisc(nd, "Received RA from non-link-local address. Ignoring.");
+                        log_ndisc(nd, "Received RA from neither link-local nor null address. Ignoring.");
                         return 0;
 
                 case -EMULTIHOP:
@@ -241,6 +241,11 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
                         return 0;
                 }
 
+        /* The function icmp6_receive() accepts the null source address, but RFC 4861 Section 6.1.2 states
+         * that hosts MUST discard messages with the null source address. */
+        if (in6_addr_is_null(&rt->address))
+                log_ndisc(nd, "Received RA from null address. Ignoring.");
+
         (void) event_source_disable(nd->timeout_event_source);
         (void) ndisc_handle_datagram(nd, rt);
         return 0;
index afb0fd95b66eb5c6a09a5e657b8c7cd5d5188579..5e25aab9b1f7a195dedade68979a944cc6e9b593 100644 (file)
@@ -264,7 +264,7 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
         if (r < 0)
                 switch (r) {
                 case -EADDRNOTAVAIL:
-                        log_radv(ra, "Received RS from non-link-local address. Ignoring");
+                        log_radv(ra, "Received RS from neither link-local nor null address. Ignoring");
                         return 0;
 
                 case -EMULTIHOP:
@@ -285,6 +285,9 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
                 return 0;
         }
 
+        /* 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. */
+
         const char *addr = IN6_ADDR_TO_STRING(&src);
 
         r = radv_send(ra, &src, ra->lifetime_usec);
index e7bf3fab589cde67213945cb37994259634b3600..baa9cb2696bb7e762294f02318b1879ff1003b67 100644 (file)
@@ -41,7 +41,8 @@ static void router_dump(sd_ndisc_router *rt) {
         assert_se(rt);
 
         log_info("--");
-        assert_se(sd_ndisc_router_get_address(rt, &addr) == -ENODATA);
+        assert_se(sd_ndisc_router_get_address(rt, &addr) >= 0);
+        log_info("Sender: %s", IN6_ADDR_TO_STRING(&addr));
 
         assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_REALTIME, &t) >= 0);
         log_info("Timestamp: %s", FORMAT_TIMESTAMP(t));
@@ -176,6 +177,13 @@ int icmp6_bind_router_advertisement(int ifindex) {
         return -ENOSYS;
 }
 
+static struct in6_addr dummy_link_local = {
+        .s6_addr = {
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x12, 0x34, 0x56, 0xff, 0xfe, 0x78, 0x9a, 0xbc,
+        },
+};
+
 int icmp6_receive(
                 int fd,
                 void *iov_base,
@@ -188,6 +196,9 @@ int icmp6_receive(
         if (ret_timestamp)
                 triple_timestamp_get(ret_timestamp);
 
+        if (ret_sender)
+                *ret_sender = dummy_link_local;
+
         return 0;
 }