diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 1b4d303fc8..f1becd4627 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -3233,6 +3233,7 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix
UseDNS=
UseDNR=
UseNTP=
+ UseSIP=
UseHostname=
UseDomains=
NetLabel=
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 6570e13d66..cae497278f 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -687,6 +687,16 @@ static int dhcp6_configure(Link *link) {
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request SNTP servers: %m");
}
+ if (link->network->dhcp6_use_sip > 0) {
+ r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SIP_SERVER_ADDRESS);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request SIP servers: %m");
+
+ r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request SIP server domain names: %m");
+ }
+
SET_FOREACH(request_options, link->network->dhcp6_request_options) {
uint32_t option = PTR_TO_UINT32(request_options);
diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c
index b6b4b02c06..aa65379acc 100644
--- a/src/network/networkd-json.c
+++ b/src/network/networkd-json.c
@@ -819,39 +819,6 @@ static int ntp_append_json(Link *link, sd_json_variant **v) {
return json_variant_set_field_non_null(v, "NTP", array);
}
-static int sip_append_json(Link *link, sd_json_variant **v) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
- const struct in_addr *sip;
- union in_addr_union s;
- int n_sip, r;
-
- assert(link);
- assert(v);
-
- if (!link->network || !link->network->dhcp_use_sip || !link->dhcp_lease)
- return 0;
-
- n_sip = sd_dhcp_lease_get_sip(link->dhcp_lease, &sip);
- if (n_sip <= 0)
- return 0;
-
- r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
- if (r < 0)
- return r;
-
- for (int i = 0; i < n_sip; i++) {
- r = server_append_json_one_addr(AF_INET,
- &(union in_addr_union) { .in = sip[i], },
- NETWORK_CONFIG_SOURCE_DHCP4,
- &s,
- &array);
- if (r < 0)
- return r;
- }
-
- return json_variant_set_field_non_null(v, "SIP", array);
-}
-
static int domain_append_json(int family, const char *domain, NetworkConfigSource s, const union in_addr_union *p, sd_json_variant **array) {
assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
assert(domain);
@@ -864,6 +831,78 @@ static int domain_append_json(int family, const char *domain, NetworkConfigSourc
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, family));
}
+static int sip_append_json(Link *link, sd_json_variant **v) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
+ int r;
+
+ assert(link);
+ assert(v);
+
+ if (!link->network)
+ return 0;
+
+ if (link->dhcp_lease && link->network->dhcp_use_sip) {
+ const struct in_addr *sip;
+ union in_addr_union s;
+ int n_sip;
+
+ n_sip = sd_dhcp_lease_get_sip(link->dhcp_lease, &sip);
+ if (n_sip <= 0)
+ return 0;
+
+ r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &s.in);
+ if (r < 0)
+ return r;
+
+ for (int i = 0; i < n_sip; i++) {
+ r = server_append_json_one_addr(AF_INET,
+ &(union in_addr_union) { .in = sip[i], },
+ NETWORK_CONFIG_SOURCE_DHCP4,
+ &s,
+ &array);
+ if (r < 0)
+ return r;
+ }
+
+ }
+
+ if (link->dhcp6_lease && link->network->dhcp6_use_sip) {
+ const struct in6_addr *sip_addr;
+ union in_addr_union s;
+ char **domains;
+ int n_sip;
+
+ r = sd_dhcp6_lease_get_server_address(link->dhcp6_lease, &s.in6);
+ if (r < 0)
+ return r;
+
+ n_sip = sd_dhcp6_lease_get_sip_addrs(link->dhcp6_lease, &sip_addr);
+ for (int i = 0; i < n_sip; i++) {
+ r = server_append_json_one_addr(AF_INET6,
+ &(union in_addr_union) { .in6 = sip_addr[i], },
+ NETWORK_CONFIG_SOURCE_DHCP6,
+ &s,
+ &array);
+ if (r < 0)
+ return r;
+ }
+
+ if (sd_dhcp6_lease_get_sip_domains(link->dhcp6_lease, &domains) >= 0)
+ STRV_FOREACH(p, domains) {
+ r = domain_append_json(AF_INET6,
+ *p,
+ NETWORK_CONFIG_SOURCE_DHCP6,
+ &s,
+ &array);
+ if (r < 0)
+ return r;
+ }
+
+ }
+
+ return json_variant_set_field_non_null(v, "SIP", array);
+}
+
static int domains_append_json(Link *link, bool is_route, sd_json_variant **v) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
OrderedSet *link_domains, *network_domains;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 577dccc9eb..52fc0ab444 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -310,6 +310,7 @@ DHCPv6.UseDNR, config_parse_tristate,
DHCPv6.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp6_use_hostname)
DHCPv6.UseDomains, config_parse_use_domains, 0, offsetof(Network, dhcp6_use_domains)
DHCPv6.UseNTP, config_parse_tristate, 0, offsetof(Network, dhcp6_use_ntp)
+DHCPv6.UseSIP, config_parse_bool, 0, offsetof(Network, dhcp6_use_sip)
DHCPv6.UseCaptivePortal, config_parse_bool, 0, offsetof(Network, dhcp6_use_captive_portal)
DHCPv6.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp6_mudurl)
DHCPv6.SendHostname, config_parse_dhcp_send_hostname, AF_INET6, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 961b431a68..e27fabea81 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -413,6 +413,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp6_use_domains = _USE_DOMAINS_INVALID,
.dhcp6_use_hostname = true,
.dhcp6_use_ntp = -1,
+ .dhcp6_use_sip = true,
.dhcp6_use_captive_portal = true,
.dhcp6_use_rapid_commit = true,
.dhcp6_send_hostname = true,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 0e14cfa7b5..677d337e0f 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -181,6 +181,7 @@ typedef struct Network {
int dhcp6_use_dnr;
bool dhcp6_use_hostname;
int dhcp6_use_ntp;
+ bool dhcp6_use_sip;
bool dhcp6_use_captive_portal;
bool dhcp6_use_rapid_commit;
UseDomains dhcp6_use_domains;
diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c
index abd8b5a4ef..21bf4b1b34 100644
--- a/src/network/networkd-state-file.c
+++ b/src/network/networkd-state-file.c
@@ -264,6 +264,25 @@ static int link_put_sip(Link *link, OrderedSet **s) {
}
}
+ if (link->dhcp6_lease && link->network->dhcp6_use_sip) {
+ const struct in6_addr *addresses;
+ char **domains;
+
+ r = sd_dhcp6_lease_get_sip_addrs(link->dhcp6_lease, &addresses);
+ if (r >= 0) {
+ r = ordered_set_put_in6_addrv(s, addresses, r);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_dhcp6_lease_get_sip_domains(link->dhcp6_lease, &domains);
+ if (r >= 0) {
+ r = ordered_set_put_strdupv_full(s, &dns_name_hash_ops_free, domains);
+ if (r < 0)
+ return r;
+ }
+ }
+
return 0;
}
@@ -842,7 +861,10 @@ static int link_save(Link *link) {
link->dhcp_lease,
link->network->dhcp_use_sip,
SD_DHCP_LEASE_SIP,
- NULL, false, NULL, NULL);
+ link->dhcp6_lease,
+ link->network->dhcp6_use_sip,
+ sd_dhcp6_lease_get_sip_addrs,
+ sd_dhcp6_lease_get_sip_domains);
/************************************************************/