]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ndisc-option: add HomeAgent option support
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 16 Mar 2024 06:52:18 +0000 (15:52 +0900)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 27 Mar 2024 13:12:30 +0000 (13:12 +0000)
Currently, these are not used, but will be used later in sd-radv.

src/libsystemd-network/ndisc-option.c
src/libsystemd-network/ndisc-option.h

index 61c58d2971758c151c9b96a9689487115f99b69c..855ec0469a70f9096aa8f4828e73afea7766ea33 100644 (file)
@@ -131,6 +131,7 @@ static int ndisc_option_compare_func(const sd_ndisc_option *x, const sd_ndisc_op
         case SD_NDISC_OPTION_TARGET_LL_ADDRESS:
         case SD_NDISC_OPTION_REDIRECTED_HEADER:
         case SD_NDISC_OPTION_MTU:
+        case SD_NDISC_OPTION_HOME_AGENT:
         case SD_NDISC_OPTION_FLAGS_EXTENSION:
         case SD_NDISC_OPTION_CAPTIVE_PORTAL:
                 /* These options cannot be specified multiple times. */
@@ -497,6 +498,63 @@ static int ndisc_option_build_mtu(const sd_ndisc_option *option, uint8_t **ret)
         return 0;
 }
 
+int ndisc_option_add_home_agent(Set **options, size_t offset, uint16_t preference, usec_t lifetime) {
+        assert(options);
+
+        if (lifetime > UINT16_MAX * USEC_PER_SEC)
+                return -EINVAL;
+
+        sd_ndisc_option *p = ndisc_option_new(SD_NDISC_OPTION_HOME_AGENT, offset);
+        if (!p)
+                return -ENOMEM;
+
+        p->home_agent = (sd_ndisc_home_agent) {
+                .preference = preference,
+                .lifetime = lifetime,
+        };
+
+        return ndisc_option_consume(options, p);
+}
+
+static int ndisc_option_parse_home_agent(Set **options, size_t offset, size_t len, const uint8_t *opt) {
+        const struct nd_opt_home_agent_info *p = (const struct nd_opt_home_agent_info*) ASSERT_PTR(opt);
+
+        assert(options);
+
+        if (len != sizeof(struct nd_opt_home_agent_info))
+                return -EBADMSG;
+
+        if (p->nd_opt_home_agent_info_type != SD_NDISC_OPTION_HOME_AGENT)
+                return -EBADMSG;
+
+        return ndisc_option_add_home_agent(
+                        options, offset,
+                        be16toh(p->nd_opt_home_agent_info_preference),
+                        be16_sec_to_usec(p->nd_opt_home_agent_info_lifetime, /* max_as_infinity = */ false));
+}
+
+static int ndisc_option_build_home_agent(const sd_ndisc_option *option, uint8_t **ret) {
+        assert(option);
+        assert(option->type == SD_NDISC_OPTION_HOME_AGENT);
+        assert(ret);
+
+        assert_cc(sizeof(struct nd_opt_home_agent_info) % 8 == 0);
+
+        _cleanup_free_ struct nd_opt_home_agent_info *buf = new(struct nd_opt_home_agent_info, 1);
+        if (!buf)
+                return -ENOMEM;
+
+        *buf = (struct nd_opt_home_agent_info) {
+                .nd_opt_home_agent_info_type = SD_NDISC_OPTION_HOME_AGENT,
+                .nd_opt_home_agent_info_len = sizeof(struct nd_opt_home_agent_info) / 8,
+                .nd_opt_home_agent_info_preference = htobe16(option->home_agent.preference),
+                .nd_opt_home_agent_info_lifetime = usec_to_be16_sec(option->home_agent.lifetime),
+        };
+
+        *ret = (uint8_t*) TAKE_PTR(buf);
+        return 0;
+}
+
 int ndisc_option_add_route(
                 Set **options,
                 size_t offset,
@@ -1121,6 +1179,10 @@ int ndisc_parse_options(ICMP6Packet *packet, Set **ret_options) {
                         r = ndisc_option_parse_mtu(&options, offset, length, opt);
                         break;
 
+                case SD_NDISC_OPTION_HOME_AGENT:
+                        r = ndisc_option_parse_home_agent(&options, offset, length, opt);
+                        break;
+
                 case SD_NDISC_OPTION_ROUTE_INFORMATION:
                         r = ndisc_option_parse_route(&options, offset, length, opt);
                         break;
@@ -1228,6 +1290,10 @@ int ndisc_send(int fd, const struct sockaddr_in6 *dst, const struct icmp6_hdr *h
                         r = ndisc_option_build_mtu(option, &buf);
                         break;
 
+                case SD_NDISC_OPTION_HOME_AGENT:
+                        r = ndisc_option_build_home_agent(option, &buf);
+                        break;
+
                 case SD_NDISC_OPTION_ROUTE_INFORMATION:
                         r = ndisc_option_build_route(option, &buf);
                         break;
index 7e7a702b809f161f325e4a01bcc6b8c097ac2b56..3bf29af0c96c92b5edc2744b0e68f60d93c4876f 100644 (file)
@@ -29,6 +29,11 @@ typedef struct sd_ndisc_prefix {
         usec_t preferred_lifetime;
 } sd_ndisc_prefix;
 
+typedef struct sd_ndisc_home_agent {
+        uint16_t preference;
+        usec_t lifetime;
+} sd_ndisc_home_agent;
+
 typedef struct sd_ndisc_route {
         uint8_t preference;
         uint8_t prefixlen;
@@ -58,17 +63,18 @@ typedef struct sd_ndisc_option {
         size_t offset;
 
         union {
-                sd_ndisc_raw raw;           /* for testing or unsupported options */
-                struct ether_addr mac;      /* SD_NDISC_OPTION_SOURCE_LL_ADDRESS or SD_NDISC_OPTION_TARGET_LL_ADDRESS */
-                sd_ndisc_prefix prefix;     /* SD_NDISC_OPTION_PREFIX_INFORMATION */
-                struct ip6_hdr hdr;         /* SD_NDISC_OPTION_REDIRECTED_HEADER */
-                uint32_t mtu;               /* SD_NDISC_OPTION_MTU */
-                sd_ndisc_route route;       /* SD_NDISC_OPTION_ROUTE_INFORMATION */
-                sd_ndisc_rdnss rdnss;       /* SD_NDISC_OPTION_RDNSS */
-                uint64_t extended_flags;    /* SD_NDISC_OPTION_FLAGS_EXTENSION */
-                sd_ndisc_dnssl dnssl;       /* SD_NDISC_OPTION_DNSSL */
-                char *captive_portal;       /* SD_NDISC_OPTION_CAPTIVE_PORTAL */
-                sd_ndisc_prefix64 prefix64; /* SD_NDISC_OPTION_PREF64 */
+                sd_ndisc_raw raw;               /* for testing or unsupported options */
+                struct ether_addr mac;          /* SD_NDISC_OPTION_SOURCE_LL_ADDRESS or SD_NDISC_OPTION_TARGET_LL_ADDRESS */
+                sd_ndisc_prefix prefix;         /* SD_NDISC_OPTION_PREFIX_INFORMATION */
+                struct ip6_hdr hdr;             /* SD_NDISC_OPTION_REDIRECTED_HEADER */
+                uint32_t mtu;                   /* SD_NDISC_OPTION_MTU */
+                sd_ndisc_home_agent home_agent; /* SD_NDISC_OPTION_HOME_AGENT */
+                sd_ndisc_route route;           /* SD_NDISC_OPTION_ROUTE_INFORMATION */
+                sd_ndisc_rdnss rdnss;           /* SD_NDISC_OPTION_RDNSS */
+                uint64_t extended_flags;        /* SD_NDISC_OPTION_FLAGS_EXTENSION */
+                sd_ndisc_dnssl dnssl;           /* SD_NDISC_OPTION_DNSSL */
+                char *captive_portal;           /* SD_NDISC_OPTION_CAPTIVE_PORTAL */
+                sd_ndisc_prefix64 prefix64;     /* SD_NDISC_OPTION_PREF64 */
         };
 } sd_ndisc_option;
 
@@ -150,6 +156,11 @@ int ndisc_option_add_mtu(
                 Set **options,
                 size_t offset,
                 uint32_t mtu);
+int ndisc_option_add_home_agent(
+                Set **options,
+                size_t offset,
+                uint16_t preference,
+                usec_t lifetime);
 int ndisc_option_add_route(
                 Set **options,
                 size_t offset,