]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-ndisc: introduce ndisc_option_parse() helper function
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 22 Feb 2024 22:27:55 +0000 (07:27 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 28 Feb 2024 02:26:52 +0000 (11:26 +0900)
src/libsystemd-network/ndisc-protocol.c
src/libsystemd-network/ndisc-protocol.h

index fae4a583ad8f1d39d707e0d149c42cec8300a190..39dcdcdfd81a1010f054205bd2f4da8b1aeed0a1 100644 (file)
@@ -1,7 +1,45 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <netinet/icmp6.h>
+
 #include "ndisc-protocol.h"
 
+int ndisc_option_parse(
+                ICMP6Packet *p,
+                size_t offset,
+                uint8_t *ret_type,
+                size_t *ret_len,
+                const uint8_t **ret_opt) {
+
+        assert(p);
+
+        if (offset == p->raw_size)
+                return -ESPIPE; /* end of the packet */
+
+        if (offset > p->raw_size)
+                return -EBADMSG;
+
+        if (p->raw_size - offset < sizeof(struct nd_opt_hdr))
+                return -EBADMSG;
+
+        const struct nd_opt_hdr *hdr = (const struct nd_opt_hdr*) (p->raw_packet + offset);
+        if (hdr->nd_opt_len == 0)
+                return -EBADMSG;
+
+        size_t len = hdr->nd_opt_len * 8;
+        if (p->raw_size - offset < len)
+                return -EBADMSG;
+
+        if (ret_type)
+                *ret_type = hdr->nd_opt_type;
+        if (ret_len)
+                *ret_len = len;
+        if (ret_opt)
+                *ret_opt = p->raw_packet + offset;
+
+        return 0;
+}
+
 static const uint8_t prefix_length_code_to_prefix_length[_PREFIX_LENGTH_CODE_MAX] = {
         [PREFIX_LENGTH_CODE_96] = 96,
         [PREFIX_LENGTH_CODE_64] = 64,
index 8e403e342550a8e2a185dca8cd8b8787f1dfb7ee..94842524ee7fb1c0c67fe7b8924216093f7a98d2 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "icmp6-packet.h"
 #include "time-util.h"
 
 /* RFC 8781: PREF64 or (NAT64 prefix) */
@@ -29,3 +30,10 @@ struct nd_opt_prefix64_info {
 
 int pref64_plc_to_prefix_length(uint16_t plc, uint8_t *ret);
 int pref64_prefix_length_to_plc(uint8_t prefixlen, uint8_t *ret);
+
+int ndisc_option_parse(
+                ICMP6Packet *p,
+                size_t offset,
+                uint8_t *ret_type,
+                size_t *ret_len,
+                const uint8_t **ret_opt);