diff options
author | Susant Sahani <ssahani@gmail.com> | 2023-08-24 20:38:48 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-09-04 16:40:40 +0200 |
commit | 6a6d27bc5b08388964118e922f0c1b49b3c6a8ae (patch) | |
tree | 342b4bb608a58936be3fc2b8cdcc1b6c1548f88d /src | |
parent | Merge pull request #28896 from pelaufer/dhcp_dbus_notify (diff) | |
download | systemd-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.h | 10 | ||||
-rw-r--r-- | src/libsystemd-network/sd-radv.c | 44 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 3 | ||||
-rw-r--r-- | src/network/networkd-network.h | 4 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 56 | ||||
-rw-r--r-- | src/network/networkd-radv.h | 1 | ||||
-rw-r--r-- | src/systemd/sd-radv.h | 5 |
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); |