]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: sd-radv - Allow to configure Mobile IPv6 Home Agent
authorSusant Sahani <ssahani@gmail.com>
Thu, 24 Aug 2023 18:38:48 +0000 (00:08 +0530)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 4 Sep 2023 14:40:40 +0000 (23:40 +0900)
man/systemd.network.xml
src/libsystemd-network/radv-internal.h
src/libsystemd-network/sd-radv.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.h
src/network/networkd-radv.c
src/network/networkd-radv.h
src/systemd/sd-radv.h

index 1f2ba9b7d4c52a48cc3a505d4a2f2fb5d9e1ea4d..5ece7b747cd973881931add450f1a549fda0ada6 100644 (file)
@@ -3661,6 +3661,37 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
         3600 seconds (one hour).</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>HomeAgent=</varname></term>
+
+        <listitem><para>Takes a boolean. Specifies that IPv6 router advertisements which indicates to hosts that
+        the router acts as a Home Agent and includes a Home Agent Option. Defaults to false. See
+        <ulink url="https://tools.ietf.org/html/rfc6275">RFC 6275</ulink> for further details.</para>
+
+         <xi:include href="version-info.xml" xpointer="v255"/>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>HomeAgentLifetimeSec=</varname></term>
+
+        <listitem><para>Takes a timespan. Specifies the lifetime of the Home Agent. An integer the default unit of seconds,
+        in the range 1…65535. Defaults to the value set to <varname>RouterLifetimeSec=</varname>.</para>
+
+         <xi:include href="version-info.xml" xpointer="v255"/>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>HomeAgentPreference=</varname></term>
+
+        <listitem><para>Configures IPv6 Home Agent preference. Takes an integer in the range 0…65535.
+        Defaults to 0.</para>
+
+         <xi:include href="version-info.xml" xpointer="v255"/>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
     </refsect1>
 
index 534d7959827d989f7159ba3969af3f8c5a885594..0667376d8867866d827acd425afbe18a5439a3aa 100644 (file)
@@ -5,6 +5,8 @@
   Copyright © 2017 Intel Corporation. All rights reserved.
 ***/
 
+#include <netinet/icmp6.h>
+
 #include "sd-radv.h"
 
 #include "list.h"
 /* Pref64 option type (RFC8781, section 4) */
 #define RADV_OPT_PREF64                           38
 
+/* rfc6275 7.4 Neighbor Discovery Home Agent Lifetime.
+ * The default value is the same as the Router Lifetime
+ * The maximum value corresponds to 18.2 hours. value of 0 MUST NOT be used.*/
+#define RADV_MAX_HOME_AGENT_LIFETIME_USEC (65535 * USEC_PER_SEC)
+
 enum RAdvState {
         RADV_STATE_IDLE                      = 0,
         RADV_STATE_ADVERTISING               = 1,
@@ -112,6 +119,9 @@ struct sd_radv {
         size_t n_rdnss;
         struct sd_radv_opt_dns *rdnss;
         struct sd_radv_opt_dns *dnssl;
+
+        /* Mobile IPv6 extension: Home Agent Info.  */
+        struct nd_opt_home_agent_info home_agent;
 };
 
 #define radv_prefix_opt__contents {             \
index cb7bc07f5af759e293b4bb3bca2bbc79de7a914c..f1256f4725b6168b969776feb5c30ee089ec137a 100644 (file)
@@ -231,6 +231,17 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_us
         if (ra->dnssl)
                 iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->dnssl, ra->dnssl->length * 8);
 
+        if (FLAGS_SET(ra->flags, ND_RA_FLAG_HOME_AGENT)) {
+                ra->home_agent.nd_opt_home_agent_info_type = ND_OPT_HOME_AGENT_INFO;
+                ra->home_agent.nd_opt_home_agent_info_len = 1;
+
+                /* 0 means to place the current Router Lifetime value */
+                if (ra->home_agent.nd_opt_home_agent_info_lifetime == 0)
+                        ra->home_agent.nd_opt_home_agent_info_lifetime = adv.nd_ra_router_lifetime;
+
+                iov[msg.msg_iovlen++] = IOVEC_MAKE(&ra->home_agent, sizeof(ra->home_agent));
+        }
+
         if (sendmsg(ra->fd, &msg, 0) < 0)
                 return -errno;
 
@@ -570,6 +581,39 @@ int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
         return 0;
 }
 
+int sd_radv_set_home_agent_information(sd_radv *ra, int home_agent) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != RADV_STATE_IDLE)
+                return -EBUSY;
+
+        SET_FLAG(ra->flags, ND_RA_FLAG_HOME_AGENT, home_agent);
+
+        return 0;
+}
+
+int sd_radv_set_home_agent_preference(sd_radv *ra, uint16_t preference) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != RADV_STATE_IDLE)
+                return -EBUSY;
+
+        ra->home_agent.nd_opt_home_agent_info_preference = htobe16(preference);
+
+        return 0;
+}
+
+int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint16_t lifetime) {
+        assert_return(ra, -EINVAL);
+
+        if (ra->state != RADV_STATE_IDLE)
+                return -EBUSY;
+
+        ra->home_agent.nd_opt_home_agent_info_lifetime = htobe16(lifetime);
+
+        return 0;
+}
+
 int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
         sd_radv_prefix *found = NULL;
         int r;
index 6309baa0569383aa71da54b2386ec9dcdcb56e8b..fefc84a7d94163e5930589a5c8330e7b26f7c545 100644 (file)
@@ -384,6 +384,9 @@ IPv6SendRA.EmitDomains,                      config_parse_bool,
 IPv6SendRA.Domains,                          config_parse_radv_search_domains,                         0,                             0
 IPv6SendRA.DNSLifetimeSec,                   config_parse_sec,                                         0,                             offsetof(Network, router_dns_lifetime_usec)
 IPv6SendRA.UplinkInterface,                  config_parse_uplink,                                      0,                             0
+IPv6SendRA.HomeAgent,                        config_parse_bool,                                        0,                             offsetof(Network, router_home_agent_information)
+IPv6SendRA.HomeAgentLifetimeSec,             config_parse_router_home_agent_lifetime,                  0,                             offsetof(Network, home_agent_lifetime_usec)
+IPv6SendRA.HomeAgentPreference,              config_parse_uint16,                                      0,                             offsetof(Network, router_home_agent_preference)
 IPv6Prefix.Prefix,                           config_parse_prefix,                                      0,                             0
 IPv6Prefix.OnLink,                           config_parse_prefix_boolean,                              0,                             0
 IPv6Prefix.AddressAutoconfiguration,         config_parse_prefix_boolean,                              0,                             0
index 19e4657f3c7c09eca301f7f822afef525d308482..a7d1f9cd28088e46b5178a8823f87687d6e21f83 100644 (file)
@@ -242,6 +242,10 @@ struct Network {
         OrderedSet *router_search_domains;
         int router_uplink_index;
         char *router_uplink_name;
+        /* Mobile IPv6 Home Agent */
+        bool router_home_agent_information;
+        uint16_t router_home_agent_preference;
+        usec_t home_agent_lifetime_usec;
 
         /* DHCP Prefix Delegation support */
         int dhcp_pd;
index 57fd68f5a0f758617ed0a4f6df01d5ac16137895..b5ee1c322d4629aeaaf7e588af33eccbb8c69f85 100644 (file)
@@ -600,6 +600,18 @@ static int radv_configure(Link *link) {
         if (r < 0)
                 return log_link_debug_errno(link, r, "Could not set RA Domains: %m");
 
+        r = sd_radv_set_home_agent_information(link->radv, link->network->router_home_agent_information);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_home_agent_preference(link->radv, link->network->router_home_agent_preference);
+        if (r < 0)
+                return r;
+
+        r = sd_radv_set_home_agent_lifetime(link->radv, DIV_ROUND_UP(link->network->home_agent_lifetime_usec, USEC_PER_SEC));
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
@@ -1575,3 +1587,47 @@ int config_parse_router_preference(
 
         return 0;
 }
+
+int config_parse_router_home_agent_lifetime(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        usec_t usec, *home_agent_lifetime_usec = ASSERT_PTR(data);
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *home_agent_lifetime_usec = 0;
+                return 0;
+        }
+
+        r = parse_sec(rvalue, &usec);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        if (usec == USEC_INFINITY || usec == 0 ||
+            DIV_ROUND_UP(usec, USEC_PER_SEC) > RADV_MAX_HOME_AGENT_LIFETIME_USEC) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Invalid %s= must be in the range 1...%lu seconds, ignoring: %s", lvalue,
+                           RADV_MAX_HOME_AGENT_LIFETIME_USEC / USEC_PER_SEC, rvalue);
+                return 0;
+        }
+
+        *home_agent_lifetime_usec = usec;
+        return 0;
+}
index 8ea1a85b26c699da6a584c34e11b3d37a3385d30..48677b50de4b775829c6debe272d17c8e67fdaab 100644 (file)
@@ -98,3 +98,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime);
 CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix);
 CONFIG_PARSER_PROTOTYPE(config_parse_pref64_prefix_lifetime);
+CONFIG_PARSER_PROTOTYPE(config_parse_router_home_agent_lifetime);
index 882613c0b3f92f23729ca617d3a9026d6a3640e5..295b8846f5a56046bae0e8faae959e7f0274322f 100644 (file)
@@ -95,6 +95,11 @@ int sd_radv_pref64_prefix_set_prefix(sd_radv_pref64_prefix *p, const struct in6_
 sd_radv_pref64_prefix *sd_radv_pref64_prefix_ref(sd_radv_pref64_prefix *ra);
 sd_radv_pref64_prefix *sd_radv_pref64_prefix_unref(sd_radv_pref64_prefix *ra);
 
+/* Mobile IPv6 extension: Home Agent Info. */
+int sd_radv_set_home_agent_information(sd_radv *ra, int home_agent);
+int sd_radv_set_home_agent_preference(sd_radv *ra, uint16_t preference);
+int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint16_t lifetime);
+
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref);