]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-radv: introduce sd_ndisc_router_solicit
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 23 Feb 2024 06:19:58 +0000 (15:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 16 Apr 2024 00:59:48 +0000 (09:59 +0900)
It is not used in this stage, but will be used later in sd-radv.

src/libsystemd-network/meson.build
src/libsystemd-network/ndisc-router-solicit-internal.h [new file with mode: 0644]
src/libsystemd-network/sd-ndisc-router-solicit.c [new file with mode: 0644]
src/systemd/meson.build
src/systemd/sd-ndisc-router-solicit.h [new file with mode: 0644]
src/systemd/sd-radv.h

index 409c893458452f6302522162061e7961bc0f1f20..fdd8806a2324bcffdba9c7c56ee7e2a1ec3a12b8 100644 (file)
@@ -31,6 +31,7 @@ sources = files(
         'sd-ndisc-neighbor.c',
         'sd-ndisc-redirect.c',
         'sd-ndisc-router.c',
+        'sd-ndisc-router-solicit.c',
         'sd-radv.c',
 )
 
diff --git a/src/libsystemd-network/ndisc-router-solicit-internal.h b/src/libsystemd-network/ndisc-router-solicit-internal.h
new file mode 100644 (file)
index 0000000..6f0b0af
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-radv.h"
+
+#include "icmp6-packet.h"
+#include "set.h"
+
+struct sd_ndisc_router_solicit {
+        unsigned n_ref;
+
+        ICMP6Packet *packet;
+
+        Set *options;
+};
+
+sd_ndisc_router_solicit* ndisc_router_solicit_new(ICMP6Packet *packet);
+int ndisc_router_solicit_parse(sd_radv *ra, sd_ndisc_router_solicit *rs);
diff --git a/src/libsystemd-network/sd-ndisc-router-solicit.c b/src/libsystemd-network/sd-ndisc-router-solicit.c
new file mode 100644 (file)
index 0000000..04e7c26
--- /dev/null
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <netinet/icmp6.h>
+
+#include "sd-radv.h"
+
+#include "alloc-util.h"
+#include "in-addr-util.h"
+#include "ndisc-option.h"
+#include "ndisc-router-solicit-internal.h"
+#include "radv-internal.h"
+
+static sd_ndisc_router_solicit* ndisc_router_solicit_free(sd_ndisc_router_solicit *rs) {
+        if (!rs)
+                return NULL;
+
+        icmp6_packet_unref(rs->packet);
+        set_free(rs->options);
+        return mfree(rs);
+}
+
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router_solicit, sd_ndisc_router_solicit, ndisc_router_solicit_free);
+
+sd_ndisc_router_solicit* ndisc_router_solicit_new(ICMP6Packet *packet) {
+        sd_ndisc_router_solicit *rs;
+
+        assert(packet);
+
+        rs = new(sd_ndisc_router_solicit, 1);
+        if (!rs)
+                return NULL;
+
+        *rs = (sd_ndisc_router_solicit) {
+                .n_ref = 1,
+                .packet = icmp6_packet_ref(packet),
+        };
+
+        return rs;
+}
+
+int ndisc_router_solicit_parse(sd_radv *ra, sd_ndisc_router_solicit *rs) {
+        int r;
+
+        assert(rs);
+        assert(rs->packet);
+
+        if (rs->packet->raw_size < sizeof(struct nd_router_solicit))
+                return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG),
+                                      "Too small to be a router solicit, ignoring.");
+
+        const struct nd_router_solicit *a = (const struct nd_router_solicit*) rs->packet->raw_packet;
+        assert(a);
+        assert(a->nd_rs_type == ND_ROUTER_SOLICIT);
+        assert(a->nd_rs_code == 0);
+
+        r = ndisc_parse_options(rs->packet, &rs->options);
+        if (r < 0)
+                return log_radv_errno(ra, r, "Failed to parse NDisc options in router solicit, ignoring datagram: %m");
+
+        /* RFC 4861 section 4.1.
+         * Source link-layer address:
+         * The link-layer address of the sender, if known. MUST NOT be included if the Source
+         * Address is the unspecified address. Otherwise, it SHOULD be included on link
+         * layers that have addresses. */
+        if (ndisc_option_get_mac(rs->options, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, NULL) >= 0&&
+            sd_ndisc_router_solicit_get_sender_address(rs, NULL) == -ENODATA)
+                return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG),
+                                      "Router Solicitation message from null address unexpectedly contains source link-layer address option, ignoring datagaram.");
+
+        return 0;
+}
+
+int sd_ndisc_router_solicit_get_sender_address(sd_ndisc_router_solicit *rs, struct in6_addr *ret) {
+        assert_return(rs, -EINVAL);
+
+        return icmp6_packet_get_sender_address(rs->packet, ret);
+}
+
+int sd_ndisc_router_solicit_get_sender_mac(sd_ndisc_router_solicit *rs, struct ether_addr *ret) {
+        assert_return(rs, -EINVAL);
+
+        return ndisc_option_get_mac(rs->options, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, ret);
+}
index e188bb99b8741a9bdbab2fe248e55848b91a3175..de58bff334c51789e5e276557ad8ecbe8a7f6fd7 100644 (file)
@@ -42,6 +42,7 @@ _not_installed_headers = [
         'sd-ndisc-protocol.h',
         'sd-ndisc-redirect.h',
         'sd-ndisc-router.h',
+        'sd-ndisc-router-solicit.h',
         'sd-netlink.h',
         'sd-network.h',
         'sd-radv.h',
diff --git a/src/systemd/sd-ndisc-router-solicit.h b/src/systemd/sd-ndisc-router-solicit.h
new file mode 100644 (file)
index 0000000..ff8c903
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#ifndef foosdndiscroutersolicitfoo
+#define foosdndiscroutersolicitfoo
+
+/***
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+
+#include "_sd-common.h"
+
+_SD_BEGIN_DECLARATIONS;
+
+typedef struct sd_ndisc_router_solicit sd_ndisc_router_solicit;
+
+sd_ndisc_router_solicit *sd_ndisc_router_solicit_ref(sd_ndisc_router_solicit *rs);
+sd_ndisc_router_solicit *sd_ndisc_router_solicit_unref(sd_ndisc_router_solicit *rs);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router_solicit, sd_ndisc_router_solicit_unref);
+
+int sd_ndisc_router_solicit_get_sender_address(sd_ndisc_router_solicit *rs, struct in6_addr *ret);
+int sd_ndisc_router_solicit_get_sender_mac(sd_ndisc_router_solicit *rs, struct ether_addr *ret);
+
+_SD_END_DECLARATIONS;
+
+#endif
index 8ea0838ee654bd00820b107e55ec8053b57780d8..79cbb8975161eb9a09ed61a89bf696fe844097e5 100644 (file)
@@ -26,7 +26,8 @@
 
 #include "_sd-common.h"
 #include "sd-event.h"
-#include "sd-ndisc.h"
+#include "sd-ndisc-protocol.h"
+#include "sd-ndisc-router-solicit.h"
 
 _SD_BEGIN_DECLARATIONS;