core: export the CLAT state over D-Bus

Export over D-Bus the CLAT state: the IPv4 and IPv6 CLAT addresses and
the NAT64 prefix.
This commit is contained in:
Beniamino Galvani 2026-01-29 18:58:32 +01:00
parent f2c5068a2b
commit da72504eed
2 changed files with 121 additions and 1 deletions

View file

@ -26,6 +26,7 @@ GType nm_ip6_config_get_type(void);
/*****************************************************************************/
#define NM_IP_CONFIG_ADDRESS_DATA "address-data"
#define NM_IP_CONFIG_CLAT_ADDRESS "clat-address"
#define NM_IP_CONFIG_DNS_OPTIONS "dns-options"
#define NM_IP_CONFIG_DNS_PRIORITY "dns-priority"
#define NM_IP_CONFIG_DOMAINS "domains"
@ -41,6 +42,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip,
NMIPConfig,
PROP_IP_L3CFG,
PROP_IP_ADDRESS_DATA,
PROP_IP_CLAT_ADDRESS,
PROP_IP_GATEWAY,
PROP_IP_ROUTE_DATA,
PROP_IP_DOMAINS,
@ -164,6 +166,8 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec
const int addr_family = nm_ip_config_get_addr_family(self);
char **to_free = NULL;
char sbuf_addr[NM_INET_ADDRSTRLEN];
in_addr_t addr4;
struct in6_addr addr6;
const char *const *strv;
guint len;
int v_i;
@ -218,6 +222,20 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec
strv = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
_value_set_variant_as(value, strv, len);
break;
case PROP_IP_CLAT_ADDRESS:
if (nm_l3_config_data_get_clat_state(priv->l3cd, &addr6, NULL, NULL, &addr4)) {
if (addr_family == AF_INET) {
g_value_set_variant(value,
g_variant_new_string(nm_inet_ntop(AF_INET, &addr4, sbuf_addr)));
} else {
g_value_set_variant(
value,
g_variant_new_string(nm_inet_ntop(AF_INET6, &addr6, sbuf_addr)));
}
} else {
g_value_set_variant(value, nm_g_variant_singleton_s_empty());
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -336,6 +354,13 @@ nm_ip_config_class_init(NMIPConfigClass *klass)
G_VARIANT_TYPE("aa{sv}"),
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties_ip[PROP_IP_CLAT_ADDRESS] =
g_param_spec_variant(NM_IP_CONFIG_CLAT_ADDRESS,
"",
"",
G_VARIANT_TYPE("s"),
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties_ip[PROP_IP_GATEWAY] =
g_param_spec_variant(NM_IP_CONFIG_GATEWAY,
"",
@ -512,6 +537,9 @@ static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
"aa{sv}",
NM_IP_CONFIG_ADDRESS_DATA),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatAddress",
"s",
NM_IP_CONFIG_CLAT_ADDRESS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
"Routes",
@ -614,6 +642,7 @@ nm_ip4_config_class_init(NMIP4ConfigClass *klass)
/*****************************************************************************/
/* public */
#define NM_IP6_CONFIG_CLAT_PREF64 "clat-pref64"
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
/* deprecated */
@ -625,6 +654,7 @@ typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip6,
NMIP6Config,
PROP_IP6_CLAT_PREF64,
PROP_IP6_NAMESERVERS,
PROP_IP6_ADDRESSES,
PROP_IP6_ROUTES, );
@ -651,6 +681,12 @@ static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
"aa{sv}",
NM_IP_CONFIG_ADDRESS_DATA),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatAddress",
"s",
NM_IP_CONFIG_CLAT_ADDRESS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("ClatPref64",
"s",
NM_IP6_CONFIG_CLAT_PREF64),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP_CONFIG_GATEWAY),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE(
"Routes",
@ -682,11 +718,24 @@ get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspe
guint len;
guint i;
const char *const *strarr;
guint8 plen;
struct in6_addr addr6;
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
switch (prop_id) {
case PROP_IP6_ADDRESSES:
g_value_set_variant(value, priv->v_addresses);
break;
case PROP_IP6_CLAT_PREF64:
if (nm_l3_config_data_get_clat_state(priv->l3cd, NULL, &addr6, &plen, NULL)) {
nm_inet6_ntop(&addr6, sbuf);
g_value_set_variant(value,
g_variant_new_string(
nm_sprintf_bufa(NM_INET_ADDRSTRLEN + 32, "%s/%u", sbuf, plen)));
} else {
g_value_set_variant(value, nm_g_variant_singleton_s_empty());
}
break;
case PROP_IP6_ROUTES:
g_value_set_variant(value, priv->v_routes);
break;
@ -740,6 +789,13 @@ nm_ip6_config_class_init(NMIP6ConfigClass *klass)
G_VARIANT_TYPE("a(ayuay)"),
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties_ip6[PROP_IP6_CLAT_PREF64] =
g_param_spec_variant(NM_IP6_CONFIG_CLAT_PREF64,
"",
"",
G_VARIANT_TYPE("s"),
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties_ip6[PROP_IP6_ROUTES] =
g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
"",
@ -787,7 +843,7 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
GParamSpec *changed_params[8];
GParamSpec *changed_params[10];
guint n_changed_params = 0;
const char *const *strarr;
const char *const *strarr_old;
@ -840,6 +896,59 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
}
}
/* CLAT state */
{
struct in6_addr clat_ip6;
struct in6_addr clat_pref64;
guint8 clat_pref64_plen;
in_addr_t clat_ip4;
gboolean clat_enabled;
struct in6_addr clat_ip6_old;
struct in6_addr clat_pref64_old;
guint8 clat_pref64_plen_old;
in_addr_t clat_ip4_old;
gboolean clat_enabled_old;
gboolean changed;
clat_enabled_old = nm_l3_config_data_get_clat_state(l3cd_old,
&clat_ip6_old,
&clat_pref64_old,
&clat_pref64_plen_old,
&clat_ip4_old);
clat_enabled = nm_l3_config_data_get_clat_state(priv->l3cd,
&clat_ip6,
&clat_pref64,
&clat_pref64_plen,
&clat_ip4);
/* CLAT address */
if (clat_enabled != clat_enabled_old) {
changed = TRUE;
} else if (!clat_enabled) {
changed = FALSE;
} else if (IS_IPv4) {
changed = (clat_ip4 != clat_ip4_old);
} else {
changed = !IN6_ARE_ADDR_EQUAL(&clat_ip6, &clat_ip6_old);
}
if (changed)
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_CLAT_ADDRESS];
/* PREF64 */
if (!IS_IPv4) {
if (clat_enabled != clat_enabled_old) {
changed = TRUE;
} else if (!clat_enabled) {
changed = FALSE;
} else {
changed = (clat_pref64_plen != clat_pref64_plen_old)
|| (!IN6_ARE_ADDR_EQUAL(&clat_pref64, &clat_pref64_old));
}
if (changed)
changed_params[n_changed_params++] = obj_properties_ip6[PROP_IP6_CLAT_PREF64];
}
}
_notify_all(self, changed_params, n_changed_params);
}

View file

@ -4351,6 +4351,17 @@ _l3cfg_update_clat_config(NML3Cfg *self,
_LOGW("Couldn't find a good ipv6 route! Unable to set up CLAT!");
}
}
if (self->priv.p->clat_address_4 && self->priv.p->clat_address_6_valid) {
nm_l3_config_data_set_clat_state(l3cd,
TRUE,
&self->priv.p->clat_address_6.address,
&pref64,
pref64_plen,
self->priv.p->clat_address_4->addr);
} else {
nm_l3_config_data_set_clat_state(l3cd, FALSE, NULL, NULL, 0, INADDR_ANY);
}
}
#endif /* HAVE_CLAT */
}