]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #29052 from yuwata/icmp6-util-cleanups
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 4 Sep 2023 15:15:23 +0000 (00:15 +0900)
committerGitHub <noreply@github.com>
Mon, 4 Sep 2023 15:15:23 +0000 (00:15 +0900)
icmp6-util: several cleanups and fixlets

src/libsystemd-network/fuzz-ndisc-rs.c
src/libsystemd-network/icmp6-util-unix.c [new file with mode: 0644]
src/libsystemd-network/icmp6-util-unix.h [new file with mode: 0644]
src/libsystemd-network/icmp6-util.c
src/libsystemd-network/icmp6-util.h
src/libsystemd-network/meson.build
src/libsystemd-network/sd-ndisc.c
src/libsystemd-network/sd-radv.c
src/libsystemd-network/test-ndisc-ra.c
src/libsystemd-network/test-ndisc-rs.c

index 7a5c45a2f97395d1d649f4b55a1f583b157d37aa..54dbfc1c76f8c9deb281431cca47e505efd922ce 100644 (file)
@@ -9,35 +9,10 @@
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fuzz.h"
-#include "icmp6-util.h"
+#include "icmp6-util-unix.h"
 #include "ndisc-internal.h"
 #include "socket-util.h"
 
-static int test_fd[2] = PIPE_EBADF;
-
-int icmp6_bind_router_solicitation(int index) {
-        assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
-        return test_fd[0];
-}
-
-int icmp6_bind_router_advertisement(int index) {
-        return -ENOSYS;
-}
-
-int icmp6_receive(int fd, void *iov_base, size_t iov_len,
-                  struct in6_addr *dst, triple_timestamp *timestamp) {
-        assert_se(read(fd, iov_base, iov_len) == (ssize_t) iov_len);
-
-        if (timestamp)
-                triple_timestamp_get(timestamp);
-
-        return 0;
-}
-
-int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-        return 0;
-}
-
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         struct ether_addr mac_addr = {
                 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
diff --git a/src/libsystemd-network/icmp6-util-unix.c b/src/libsystemd-network/icmp6-util-unix.c
new file mode 100644 (file)
index 0000000..bbb3bc8
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <netinet/ip6.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "icmp6-util-unix.h"
+
+send_ra_t send_ra_function = NULL;
+int test_fd[2] = PIPE_EBADF;
+
+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_bind_router_solicitation(int ifindex) {
+        if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
+                return -errno;
+
+        return test_fd[0];
+}
+
+int icmp6_bind_router_advertisement(int ifindex) {
+        return test_fd[1];
+}
+
+int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
+        if (!send_ra_function)
+                return 0;
+
+        return send_ra_function(0);
+}
+
+int icmp6_receive(
+                int fd,
+                void *iov_base,
+                size_t iov_len,
+                struct in6_addr *ret_sender,
+                triple_timestamp *ret_timestamp) {
+
+        assert_se(read (fd, iov_base, iov_len) == (ssize_t) iov_len);
+
+        if (ret_timestamp)
+                triple_timestamp_get(ret_timestamp);
+
+        if (ret_sender)
+                *ret_sender = dummy_link_local;
+
+        return 0;
+}
diff --git a/src/libsystemd-network/icmp6-util-unix.h b/src/libsystemd-network/icmp6-util-unix.h
new file mode 100644 (file)
index 0000000..a9cb05a
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "icmp6-util.h"
+
+typedef int (*send_ra_t)(uint8_t flags);
+
+extern send_ra_t send_ra_function;
+extern int test_fd[2];
index ecddab61e42381ca2aa6f0aa71436c313ce61f00..ecd0dd0f3175911a45c24c5e96d4c82f98b5f0d4 100644 (file)
@@ -144,8 +144,12 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
         return 0;
 }
 
-int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
-                  triple_timestamp *ret_timestamp) {
+int icmp6_receive(
+                int fd,
+                void *buffer,
+                size_t size,
+                struct in6_addr *ret_sender,
+                triple_timestamp *ret_timestamp) {
 
         /* This needs to be initialized with zero. See #20741. */
         CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int)) + /* ttl */
@@ -178,7 +182,7 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
             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)
@@ -206,10 +210,14 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
                 }
         }
 
-        if (!triple_timestamp_is_set(&t))
-                triple_timestamp_get(&t);
+        if (ret_timestamp) {
+                if (triple_timestamp_is_set(&t))
+                        *ret_timestamp = t;
+                else
+                        triple_timestamp_get(ret_timestamp);
+        }
 
-        *ret_dst = addr;
-        *ret_timestamp = t;
+        if (ret_sender)
+                *ret_sender = addr;
         return 0;
 }
index f7ad26b5e61995486aa82e21ba73277f00d02c8a..0a9ecb4c44d72cdc7c1481a5646a7a4a00e58bef 100644 (file)
@@ -20,5 +20,9 @@
 int icmp6_bind_router_solicitation(int ifindex);
 int icmp6_bind_router_advertisement(int ifindex);
 int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr);
-int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
-                  triple_timestamp *ret_timestamp);
+int icmp6_receive(
+                int fd,
+                void *buffer,
+                size_t size,
+                struct in6_addr *ret_sender,
+                triple_timestamp *ret_timestamp);
index 80762a72c07ff774c31939f059fb3233d2d06288..3eba57f991f82a5063dabf21d2e8af33806ecde8 100644 (file)
@@ -84,10 +84,16 @@ executables += [
                 'sources' : files('test-lldp-rx.c'),
         },
         network_test_template + {
-                'sources' : files('test-ndisc-ra.c'),
+                'sources' : files(
+                        'test-ndisc-ra.c',
+                        'icmp6-util-unix.c',
+                ),
         },
         network_test_template + {
-                'sources' : files('test-ndisc-rs.c'),
+                'sources' : files(
+                        'test-ndisc-rs.c',
+                        'icmp6-util-unix.c',
+                ),
         },
         network_test_template + {
                 'sources' : files('test-sd-dhcp-lease.c'),
@@ -108,6 +114,9 @@ executables += [
                 'sources' : files('fuzz-lldp-rx.c'),
         },
         network_fuzz_template + {
-                'sources' : files('fuzz-ndisc-rs.c'),
+                'sources' : files(
+                        'fuzz-ndisc-rs.c',
+                        'icmp6-util-unix.c',
+                ),
         },
 ]
index ca5365b95ffec647633a357610b7a52a008fae65..d7d9e7e2d9f3299614dad60d89374545efe8130d 100644 (file)
@@ -225,8 +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 %s. Ignoring.",
-                                  IN6_ADDR_TO_STRING(&rt->address));
+                        log_ndisc(nd, "Received RA from neither link-local nor null address. Ignoring.");
                         return 0;
 
                 case -EMULTIHOP:
@@ -242,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 c99b2b2313c25aca49ebb66594a6e9f209fefc79..a35311efb99c6aae392afd214bef5361a632d6ec 100644 (file)
@@ -275,8 +275,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 %s. Ignoring",
-                                 IN6_ADDR_TO_STRING(&src));
+                        log_radv(ra, "Received RS from neither link-local nor null address. Ignoring");
                         return 0;
 
                 case -EMULTIHOP:
@@ -297,6 +296,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 bd8c0fd426a1dcbd115fc883778e0f1fdb3cddeb..18004f64665255c402fa9d18ff1998581990f2ab 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "alloc-util.h"
 #include "hexdecoct.h"
-#include "icmp6-util.h"
+#include "icmp6-util-unix.h"
 #include "socket-util.h"
 #include "strv.h"
 #include "tests.h"
@@ -52,7 +52,6 @@ static uint8_t advertisement[] = {
 };
 
 static bool test_stopped;
-static int test_fd[2];
 static struct {
         struct in6_addr address;
         unsigned char prefixlen;
@@ -208,31 +207,6 @@ TEST(radv) {
         assert_se(!ra);
 }
 
-int icmp6_bind_router_solicitation(int ifindex) {
-        return -ENOSYS;
-}
-
-int icmp6_bind_router_advertisement(int ifindex) {
-        assert_se(ifindex == 42);
-
-        return test_fd[1];
-}
-
-int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-
-        return 0;
-}
-
-int icmp6_receive(int fd, void *iov_base, size_t iov_len,
-                  struct in6_addr *dst, triple_timestamp *timestamp) {
-        assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
-
-        if (timestamp)
-                triple_timestamp_get(timestamp);
-
-        return 0;
-}
-
 static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         sd_radv *ra = userdata;
         unsigned char buf[168];
index e501b6437744bc21edc16e5c99f362b0d2460d8e..09e292a2ec36d9da8360b19d8c9b118e24f9d573 100644 (file)
@@ -12,7 +12,7 @@
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "hexdecoct.h"
-#include "icmp6-util.h"
+#include "icmp6-util-unix.h"
 #include "socket-util.h"
 #include "strv.h"
 #include "ndisc-internal.h"
@@ -23,12 +23,8 @@ static struct ether_addr mac_addr = {
 };
 
 static bool verbose = false;
-static int test_fd[2];
 static sd_ndisc *test_timeout_nd;
 
-typedef int (*send_ra_t)(uint8_t flags);
-static send_ra_t send_ra_function;
-
 static void router_dump(sd_ndisc_router *rt) {
         struct in6_addr addr;
         uint8_t hop_limit;
@@ -41,7 +37,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));
@@ -163,29 +160,6 @@ static void router_dump(sd_ndisc_router *rt) {
         }
 }
 
-int icmp6_bind_router_solicitation(int ifindex) {
-        assert_se(ifindex == 42);
-
-        if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
-                return -errno;
-
-        return test_fd[0];
-}
-
-int icmp6_bind_router_advertisement(int ifindex) {
-        return -ENOSYS;
-}
-
-int icmp6_receive(int fd, void *iov_base, size_t iov_len,
-                  struct in6_addr *dst, triple_timestamp *timestamp) {
-        assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len);
-
-        if (timestamp)
-                triple_timestamp_get(timestamp);
-
-        return 0;
-}
-
 static int send_ra(uint8_t flags) {
         uint8_t advertisement[] = {
                 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
@@ -214,13 +188,6 @@ static int send_ra(uint8_t flags) {
         return 0;
 }
 
-int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
-        if (!send_ra_function)
-                return 0;
-
-        return send_ra_function(0);
-}
-
 static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata) {
         sd_event *e = userdata;
         static unsigned idx = 0;