summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@gmail.com>2023-08-24 20:38:48 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-09-04 16:40:40 +0200
commit6a6d27bc5b08388964118e922f0c1b49b3c6a8ae (patch)
tree342b4bb608a58936be3fc2b8cdcc1b6c1548f88d /src
parentMerge pull request #28896 from pelaufer/dhcp_dbus_notify (diff)
downloadsystemd-6a6d27bc5b08388964118e922f0c1b49b3c6a8ae.tar.xz
systemd-6a6d27bc5b08388964118e922f0c1b49b3c6a8ae.zip
network: sd-radv - Allow to configure Mobile IPv6 Home Agent
Diffstat (limited to 'src')
-rw-r--r--src/libsystemd-network/radv-internal.h10
-rw-r--r--src/libsystemd-network/sd-radv.c44
-rw-r--r--src/network/networkd-network-gperf.gperf3
-rw-r--r--src/network/networkd-network.h4
-rw-r--r--src/network/networkd-radv.c56
-rw-r--r--src/network/networkd-radv.h1
-rw-r--r--src/systemd/sd-radv.h5
7 files changed, 123 insertions, 0 deletions
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
index 534d795982..0667376d88 100644
--- a/src/libsystemd-network/radv-internal.h
+++ b/src/libsystemd-network/radv-internal.h
@@ -5,6 +5,8 @@
Copyright © 2017 Intel Corporation. All rights reserved.
***/
+#include <netinet/icmp6.h>
+
#include "sd-radv.h"
#include "list.h"
@@ -65,6 +67,11 @@
/* 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 { \
diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c
index cb7bc07f5a..f1256f4725 100644
--- a/src/libsystemd-network/sd-radv.c
+++ b/src/libsystemd-network/sd-radv.c
@@ -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;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 6309baa056..fefc84a7d9 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -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
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 19e4657f3c..a7d1f9cd28 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -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;
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
index 57fd68f5a0..b5ee1c322d 100644
--- a/src/network/networkd-radv.c
+++ b/src/network/networkd-radv.c
@@ -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;
+}
diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h
index 8ea1a85b26..48677b50de 100644
--- a/src/network/networkd-radv.h
+++ b/src/network/networkd-radv.h
@@ -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);
diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h
index 882613c0b3..295b8846f5 100644
--- a/src/systemd/sd-radv.h
+++ b/src/systemd/sd-radv.h
@@ -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);