libnm: add API to NMSettingIPConfig for routing rules
This commit is contained in:
@@ -541,6 +541,7 @@ typedef struct {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
BUILD_LIST_TYPE_ADDRESSES,
|
BUILD_LIST_TYPE_ADDRESSES,
|
||||||
BUILD_LIST_TYPE_ROUTES,
|
BUILD_LIST_TYPE_ROUTES,
|
||||||
|
BUILD_LIST_TYPE_ROUTING_RULES,
|
||||||
} BuildListType;
|
} BuildListType;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -661,6 +662,12 @@ _build_list_create (GKeyFile *keyfile,
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
case BUILD_LIST_TYPE_ROUTING_RULES:
|
||||||
|
if (_build_list_match_key_w_name (s_key, "routing-rule", &key_idx))
|
||||||
|
key_type = 0;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
nm_assert_not_reached ();
|
nm_assert_not_reached ();
|
||||||
break;
|
break;
|
||||||
@@ -759,6 +766,63 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||||||
g_object_set (setting, "gateway", gateway, NULL);
|
g_object_set (setting, "gateway", gateway, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ip_routing_rule_parser_full (KeyfileReaderInfo *info,
|
||||||
|
const NMMetaSettingInfo *setting_info,
|
||||||
|
const NMSettInfoProperty *property_info,
|
||||||
|
const ParseInfoProperty *pip,
|
||||||
|
NMSetting *setting)
|
||||||
|
{
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
gboolean is_ipv6 = nm_streq (setting_name, "ipv6");
|
||||||
|
gs_strfreev char **keys = NULL;
|
||||||
|
gs_free BuildListData *build_list = NULL;
|
||||||
|
gsize i_build_list, build_list_len = 0;
|
||||||
|
|
||||||
|
build_list = _build_list_create (info->keyfile,
|
||||||
|
setting_name,
|
||||||
|
BUILD_LIST_TYPE_ROUTING_RULES,
|
||||||
|
&build_list_len,
|
||||||
|
&keys);
|
||||||
|
if (!build_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) {
|
||||||
|
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL;
|
||||||
|
gs_free char *value = NULL;
|
||||||
|
gs_free_error GError *local = NULL;
|
||||||
|
|
||||||
|
if (_build_list_data_is_shadowed (build_list, build_list_len, i_build_list))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
value = nm_keyfile_plugin_kf_get_string (info->keyfile,
|
||||||
|
setting_name,
|
||||||
|
build_list[i_build_list].s_key,
|
||||||
|
NULL);
|
||||||
|
if (!value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rule = nm_ip_routing_rule_from_string (value,
|
||||||
|
( NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||||
|
| ( is_ipv6
|
||||||
|
? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6
|
||||||
|
: NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET)),
|
||||||
|
NULL,
|
||||||
|
&local);
|
||||||
|
if (!rule) {
|
||||||
|
handle_warn (info, property_info->name, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||||
|
_("invalid value for \"%s\": %s"),
|
||||||
|
build_list[i_build_list].s_key,
|
||||||
|
local->message);
|
||||||
|
if (info->error)
|
||||||
|
return;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_setting_ip_config_add_routing_rule (NM_SETTING_IP_CONFIG (setting), rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||||
{
|
{
|
||||||
@@ -1962,6 +2026,40 @@ bridge_vlan_writer (KeyfileWriterInfo *info,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ip_routing_rule_writer_full (KeyfileWriterInfo *info,
|
||||||
|
const NMMetaSettingInfo *setting_info,
|
||||||
|
const NMSettInfoProperty *property_info,
|
||||||
|
const ParseInfoProperty *pip,
|
||||||
|
NMSetting *setting)
|
||||||
|
{
|
||||||
|
const char *setting_name = nm_setting_get_name (setting);
|
||||||
|
NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
|
||||||
|
guint i, j, n;
|
||||||
|
char key_name_full[100] = "routing-rule";
|
||||||
|
char *key_name_num = &key_name_full[NM_STRLEN ("routing-rule")];
|
||||||
|
|
||||||
|
n = nm_setting_ip_config_get_num_routing_rules (s_ip);
|
||||||
|
j = 0;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
NMIPRoutingRule *rule = nm_setting_ip_config_get_routing_rule (s_ip, i);
|
||||||
|
gs_free char *str = NULL;
|
||||||
|
|
||||||
|
str = nm_ip_routing_rule_to_string (rule,
|
||||||
|
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!str)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf (key_name_num, "%u", ++j);
|
||||||
|
nm_keyfile_plugin_kf_set_string (info->keyfile,
|
||||||
|
setting_name,
|
||||||
|
key_name_full,
|
||||||
|
str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qdisc_writer (KeyfileWriterInfo *info,
|
qdisc_writer (KeyfileWriterInfo *info,
|
||||||
NMSetting *setting,
|
NMSetting *setting,
|
||||||
@@ -2463,6 +2561,13 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
|
|||||||
.parser = ip_address_or_route_parser,
|
.parser = ip_address_or_route_parser,
|
||||||
.writer = route_writer,
|
.writer = route_writer,
|
||||||
),
|
),
|
||||||
|
PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ROUTING_RULES,
|
||||||
|
.parser_no_check_key = TRUE,
|
||||||
|
.parser_full = ip_routing_rule_parser_full,
|
||||||
|
.writer_full = ip_routing_rule_writer_full,
|
||||||
|
.has_parser_full = TRUE,
|
||||||
|
.has_writer_full = TRUE,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG,
|
PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG,
|
||||||
@@ -2491,6 +2596,13 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
|
|||||||
.parser = ip_address_or_route_parser,
|
.parser = ip_address_or_route_parser,
|
||||||
.writer = route_writer,
|
.writer = route_writer,
|
||||||
),
|
),
|
||||||
|
PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ROUTING_RULES,
|
||||||
|
.parser_no_check_key = TRUE,
|
||||||
|
.parser_full = ip_routing_rule_parser_full,
|
||||||
|
.writer_full = ip_routing_rule_writer_full,
|
||||||
|
.has_parser_full = TRUE,
|
||||||
|
.has_writer_full = TRUE,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL,
|
PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL,
|
||||||
|
@@ -3533,6 +3533,7 @@ typedef struct {
|
|||||||
int dns_priority;
|
int dns_priority;
|
||||||
GPtrArray *addresses; /* array of NMIPAddress */
|
GPtrArray *addresses; /* array of NMIPAddress */
|
||||||
GPtrArray *routes; /* array of NMIPRoute */
|
GPtrArray *routes; /* array of NMIPRoute */
|
||||||
|
GPtrArray *routing_rules;
|
||||||
gint64 route_metric;
|
gint64 route_metric;
|
||||||
guint32 route_table;
|
guint32 route_table;
|
||||||
char *gateway;
|
char *gateway;
|
||||||
@@ -4434,6 +4435,225 @@ nm_setting_ip_config_get_route_table (NMSettingIPConfig *setting)
|
|||||||
return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_table;
|
return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_routing_rules_notify (NMSettingIPConfig *setting)
|
||||||
|
{
|
||||||
|
_nm_setting_emit_property_changed (NM_SETTING (setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_ip_config_get_num_routing_rules:
|
||||||
|
* @setting: the #NMSettingIPConfig
|
||||||
|
*
|
||||||
|
* Returns: the number of configured routing rules
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
guint
|
||||||
|
nm_setting_ip_config_get_num_routing_rules (NMSettingIPConfig *setting)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
|
||||||
|
|
||||||
|
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
return priv->routing_rules ? priv->routing_rules->len : 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_ip_config_get_routing_rule:
|
||||||
|
* @setting: the #NMSettingIPConfig
|
||||||
|
* @idx: index number of the routing_rule to return
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the routing rule at index @idx
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
NMIPRoutingRule *
|
||||||
|
nm_setting_ip_config_get_routing_rule (NMSettingIPConfig *setting, guint idx)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
|
||||||
|
|
||||||
|
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
|
||||||
|
g_return_val_if_fail (priv->routing_rules && idx < priv->routing_rules->len, NULL);
|
||||||
|
|
||||||
|
return priv->routing_rules->pdata[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_ip_config_add_routing_rule:
|
||||||
|
* @setting: the #NMSettingIPConfig
|
||||||
|
* @routing_rule: the #NMIPRoutingRule to add. The address family
|
||||||
|
* of the added rule must be compatible with the setting.
|
||||||
|
*
|
||||||
|
* Appends a new routing-rule and associated information to the setting. The
|
||||||
|
* given routing rules gets sealed and the reference count is incremented.
|
||||||
|
* The function does not check whether an identical rule already exists
|
||||||
|
* and always appends the rule to the end of the list.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
nm_setting_ip_config_add_routing_rule (NMSettingIPConfig *setting,
|
||||||
|
NMIPRoutingRule *routing_rule)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
|
||||||
|
g_return_if_fail (NM_IS_IP_ROUTING_RULE (routing_rule, TRUE));
|
||||||
|
g_return_if_fail (_ip_routing_rule_get_addr_family (routing_rule) == NM_SETTING_IP_CONFIG_GET_FAMILY (setting));
|
||||||
|
|
||||||
|
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
|
||||||
|
if (!priv->routing_rules)
|
||||||
|
priv->routing_rules = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_routing_rule_unref);
|
||||||
|
|
||||||
|
nm_ip_routing_rule_seal (routing_rule);
|
||||||
|
g_ptr_array_add (priv->routing_rules, nm_ip_routing_rule_ref (routing_rule));
|
||||||
|
_routing_rules_notify (setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_ip_config_remove_routing_rule:
|
||||||
|
* @setting: the #NMSettingIPConfig
|
||||||
|
* @idx: index number of the routing_rule
|
||||||
|
*
|
||||||
|
* Removes the routing_rule at index @idx.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
nm_setting_ip_config_remove_routing_rule (NMSettingIPConfig *setting,
|
||||||
|
guint idx)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
|
||||||
|
|
||||||
|
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
g_return_if_fail (priv->routing_rules && idx < priv->routing_rules->len);
|
||||||
|
|
||||||
|
g_ptr_array_remove_index (priv->routing_rules, idx);
|
||||||
|
_routing_rules_notify (setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_setting_ip_config_clear_routing_rules:
|
||||||
|
* @setting: the #NMSettingIPConfig
|
||||||
|
*
|
||||||
|
* Removes all configured routing rules.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
nm_setting_ip_config_clear_routing_rules (NMSettingIPConfig *setting)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
|
||||||
|
g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
|
||||||
|
|
||||||
|
if ( priv->routing_rules
|
||||||
|
&& priv->routing_rules->len > 0) {
|
||||||
|
g_ptr_array_set_size (priv->routing_rules, 0);
|
||||||
|
_routing_rules_notify (setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
_routing_rules_dbus_only_synth (const NMSettInfoSetting *sett_info,
|
||||||
|
guint property_idx,
|
||||||
|
NMConnection *connection,
|
||||||
|
NMSetting *setting,
|
||||||
|
NMConnectionSerializationFlags flags)
|
||||||
|
{
|
||||||
|
NMSettingIPConfig *self = NM_SETTING_IP_CONFIG (setting);
|
||||||
|
NMSettingIPConfigPrivate *priv;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
gboolean any = FALSE;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if ( !priv->routing_rules
|
||||||
|
|| priv->routing_rules->len == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->routing_rules->len; i++) {
|
||||||
|
GVariant *variant;
|
||||||
|
|
||||||
|
variant = nm_ip_routing_rule_to_dbus (priv->routing_rules->pdata[i]);
|
||||||
|
if (!variant)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!any) {
|
||||||
|
any = TRUE;
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
|
||||||
|
}
|
||||||
|
g_variant_builder_add (&builder, "@a{sv}", variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
return any ? g_variant_builder_end (&builder) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_routing_rules_dbus_only_set (NMSetting *setting,
|
||||||
|
GVariant *connection_dict,
|
||||||
|
const char *property,
|
||||||
|
GVariant *value,
|
||||||
|
NMSettingParseFlags parse_flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GVariantIter iter_rules;
|
||||||
|
GVariant *rule_var;
|
||||||
|
guint i_rule;
|
||||||
|
gboolean success = FALSE;
|
||||||
|
gboolean rules_changed = FALSE;
|
||||||
|
|
||||||
|
nm_assert (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")));
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter_rules, value);
|
||||||
|
|
||||||
|
i_rule = 0;
|
||||||
|
while (g_variant_iter_next (&iter_rules, "@a{sv}", &rule_var)) {
|
||||||
|
_nm_unused gs_unref_variant GVariant *rule_var_unref = rule_var;
|
||||||
|
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL;
|
||||||
|
gs_free_error GError *local = NULL;
|
||||||
|
|
||||||
|
i_rule++;
|
||||||
|
|
||||||
|
rule = nm_ip_routing_rule_from_dbus (rule_var,
|
||||||
|
NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT),
|
||||||
|
&local);
|
||||||
|
if (!rule) {
|
||||||
|
if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
|
||||||
|
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY,
|
||||||
|
_("rule #%u is invalid: %s"),
|
||||||
|
i_rule,
|
||||||
|
local->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_setting_ip_config_add_routing_rule (NM_SETTING_IP_CONFIG (setting), rule);
|
||||||
|
rules_changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = TRUE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (rules_changed)
|
||||||
|
_routing_rules_notify (NM_SETTING_IP_CONFIG (setting));
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_setting_ip_config_get_ignore_auto_routes:
|
* nm_setting_ip_config_get_ignore_auto_routes:
|
||||||
* @setting: the #NMSettingIPConfig
|
* @setting: the #NMSettingIPConfig
|
||||||
@@ -4720,6 +4940,33 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->routing_rules) {
|
||||||
|
for (i = 0; i < priv->routing_rules->len; i++) {
|
||||||
|
NMIPRoutingRule *rule = priv->routing_rules->pdata[i];
|
||||||
|
gs_free_error GError *local = NULL;
|
||||||
|
|
||||||
|
if (_ip_routing_rule_get_addr_family (rule) != NM_SETTING_IP_CONFIG_GET_FAMILY (setting)) {
|
||||||
|
g_set_error (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("%u. rule has wrong address-family"),
|
||||||
|
i + 1);
|
||||||
|
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTING_RULES);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!nm_ip_routing_rule_validate (rule, &local)) {
|
||||||
|
g_set_error (error,
|
||||||
|
NM_CONNECTION_ERROR,
|
||||||
|
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||||
|
_("%u. rule is invalid: %s"),
|
||||||
|
i + 1,
|
||||||
|
local->message);
|
||||||
|
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->gateway && priv->never_default) {
|
if (priv->gateway && priv->never_default) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
NM_CONNECTION_ERROR,
|
NM_CONNECTION_ERROR,
|
||||||
@@ -4774,6 +5021,24 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ROUTING_RULES)) {
|
||||||
|
if (other) {
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
|
||||||
|
|
||||||
|
n = (a_priv->routing_rules) ? a_priv->routing_rules->len : 0u;
|
||||||
|
if (n != (b_priv->routing_rules ? b_priv->routing_rules->len : 0u))
|
||||||
|
return FALSE;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (nm_ip_routing_rule_cmp (a_priv->routing_rules->pdata[i], b_priv->routing_rules->pdata[i]) != 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return NM_SETTING_CLASS (nm_setting_ip_config_parent_class)->compare_property (sett_info,
|
return NM_SETTING_CLASS (nm_setting_ip_config_parent_class)->compare_property (sett_info,
|
||||||
property_idx,
|
property_idx,
|
||||||
setting,
|
setting,
|
||||||
@@ -4781,6 +5046,72 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
duplicate_copy_properties (const NMSettInfoSetting *sett_info,
|
||||||
|
NMSetting *src,
|
||||||
|
NMSetting *dst)
|
||||||
|
{
|
||||||
|
NMSettingIPConfigPrivate *priv_src = NM_SETTING_IP_CONFIG_GET_PRIVATE (src);
|
||||||
|
NMSettingIPConfigPrivate *priv_dst = NM_SETTING_IP_CONFIG_GET_PRIVATE (dst);
|
||||||
|
guint i;
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
|
||||||
|
NM_SETTING_CLASS (nm_setting_ip_config_parent_class)->duplicate_copy_properties (sett_info,
|
||||||
|
src,
|
||||||
|
dst);
|
||||||
|
|
||||||
|
if ( priv_dst->routing_rules
|
||||||
|
&& priv_dst->routing_rules->len > 0) {
|
||||||
|
changed = TRUE;
|
||||||
|
g_ptr_array_set_size (priv_dst->routing_rules, 0);
|
||||||
|
}
|
||||||
|
if ( priv_src->routing_rules
|
||||||
|
&& priv_src->routing_rules->len > 0) {
|
||||||
|
changed = TRUE;
|
||||||
|
if (!priv_dst->routing_rules)
|
||||||
|
priv_dst->routing_rules = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_routing_rule_unref);
|
||||||
|
for (i = 0; i < priv_src->routing_rules->len; i++) {
|
||||||
|
g_ptr_array_add (priv_dst->routing_rules,
|
||||||
|
nm_ip_routing_rule_ref (priv_src->routing_rules->pdata[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
_routing_rules_notify (NM_SETTING_IP_CONFIG (dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enumerate_values (const NMSettInfoProperty *property_info,
|
||||||
|
NMSetting *setting,
|
||||||
|
NMSettingValueIterFn func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (nm_streq (property_info->name, NM_SETTING_IP_CONFIG_ROUTING_RULES)) {
|
||||||
|
NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
|
||||||
|
nm_auto_unset_gvalue GValue value = G_VALUE_INIT;
|
||||||
|
GPtrArray *ptr = NULL;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (priv->routing_rules && priv->routing_rules->len > 0) {
|
||||||
|
ptr = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_routing_rule_unref);
|
||||||
|
for (i = 0; i < priv->routing_rules->len; i++)
|
||||||
|
g_ptr_array_add (ptr, nm_ip_routing_rule_ref (priv->routing_rules->pdata[i]));
|
||||||
|
}
|
||||||
|
g_value_init (&value, G_TYPE_PTR_ARRAY);
|
||||||
|
g_value_take_boxed (&value, ptr);
|
||||||
|
func (setting,
|
||||||
|
property_info->name,
|
||||||
|
&value,
|
||||||
|
0,
|
||||||
|
user_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_SETTING_CLASS (nm_setting_ip_config_parent_class)->enumerate_values (property_info,
|
||||||
|
setting,
|
||||||
|
func,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -4813,6 +5144,18 @@ _nm_sett_info_property_override_create_array_ip_config (void)
|
|||||||
ip_gateway_set,
|
ip_gateway_set,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* ---dbus---
|
||||||
|
* property: routing-rules
|
||||||
|
* format: array of 'a{sv}'
|
||||||
|
* description: Array of dictionaries for routing rules.
|
||||||
|
* ---end---
|
||||||
|
*/
|
||||||
|
_properties_override_add_dbus_only (properties_override,
|
||||||
|
NM_SETTING_IP_CONFIG_ROUTING_RULES,
|
||||||
|
G_VARIANT_TYPE ("aa{sv}"),
|
||||||
|
_routing_rules_dbus_only_synth,
|
||||||
|
_routing_rules_dbus_only_set);
|
||||||
|
|
||||||
return properties_override;
|
return properties_override;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5020,6 +5363,8 @@ finalize (GObject *object)
|
|||||||
g_ptr_array_unref (priv->dns_options);
|
g_ptr_array_unref (priv->dns_options);
|
||||||
g_ptr_array_unref (priv->addresses);
|
g_ptr_array_unref (priv->addresses);
|
||||||
g_ptr_array_unref (priv->routes);
|
g_ptr_array_unref (priv->routes);
|
||||||
|
if (priv->routing_rules)
|
||||||
|
g_ptr_array_unref (priv->routing_rules);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_setting_ip_config_parent_class)->finalize (object);
|
G_OBJECT_CLASS (nm_setting_ip_config_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@@ -5038,6 +5383,8 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass)
|
|||||||
|
|
||||||
setting_class->verify = verify;
|
setting_class->verify = verify;
|
||||||
setting_class->compare_property = compare_property;
|
setting_class->compare_property = compare_property;
|
||||||
|
setting_class->duplicate_copy_properties = duplicate_copy_properties;
|
||||||
|
setting_class->enumerate_values = enumerate_values;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NMSettingIPConfig:method:
|
* NMSettingIPConfig:method:
|
||||||
|
@@ -334,6 +334,9 @@ char *nm_ip_routing_rule_to_string (const NMIPRoutingRule *self,
|
|||||||
#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout"
|
#define NM_SETTING_IP_CONFIG_DAD_TIMEOUT "dad-timeout"
|
||||||
#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout"
|
#define NM_SETTING_IP_CONFIG_DHCP_TIMEOUT "dhcp-timeout"
|
||||||
|
|
||||||
|
/* these are not real GObject properties. */
|
||||||
|
#define NM_SETTING_IP_CONFIG_ROUTING_RULES "routing-rules"
|
||||||
|
|
||||||
#define NM_SETTING_DNS_OPTION_DEBUG "debug"
|
#define NM_SETTING_DNS_OPTION_DEBUG "debug"
|
||||||
#define NM_SETTING_DNS_OPTION_NDOTS "ndots"
|
#define NM_SETTING_DNS_OPTION_NDOTS "ndots"
|
||||||
#define NM_SETTING_DNS_OPTION_TIMEOUT "timeout"
|
#define NM_SETTING_DNS_OPTION_TIMEOUT "timeout"
|
||||||
@@ -436,6 +439,20 @@ gint64 nm_setting_ip_config_get_route_metric (NMSettingIPConfig
|
|||||||
NM_AVAILABLE_IN_1_10
|
NM_AVAILABLE_IN_1_10
|
||||||
guint32 nm_setting_ip_config_get_route_table (NMSettingIPConfig *setting);
|
guint32 nm_setting_ip_config_get_route_table (NMSettingIPConfig *setting);
|
||||||
|
|
||||||
|
NM_AVAILABLE_IN_1_18
|
||||||
|
guint nm_setting_ip_config_get_num_routing_rules (NMSettingIPConfig *setting);
|
||||||
|
NM_AVAILABLE_IN_1_18
|
||||||
|
NMIPRoutingRule *nm_setting_ip_config_get_routing_rule (NMSettingIPConfig *setting,
|
||||||
|
guint idx);
|
||||||
|
NM_AVAILABLE_IN_1_18
|
||||||
|
void nm_setting_ip_config_add_routing_rule (NMSettingIPConfig *setting,
|
||||||
|
NMIPRoutingRule *routing_rule);
|
||||||
|
NM_AVAILABLE_IN_1_18
|
||||||
|
void nm_setting_ip_config_remove_routing_rule (NMSettingIPConfig *setting,
|
||||||
|
guint idx);
|
||||||
|
NM_AVAILABLE_IN_1_18
|
||||||
|
void nm_setting_ip_config_clear_routing_rules (NMSettingIPConfig *setting);
|
||||||
|
|
||||||
gboolean nm_setting_ip_config_get_ignore_auto_routes (NMSettingIPConfig *setting);
|
gboolean nm_setting_ip_config_get_ignore_auto_routes (NMSettingIPConfig *setting);
|
||||||
gboolean nm_setting_ip_config_get_ignore_auto_dns (NMSettingIPConfig *setting);
|
gboolean nm_setting_ip_config_get_ignore_auto_dns (NMSettingIPConfig *setting);
|
||||||
|
|
||||||
|
@@ -2710,6 +2710,7 @@ test_connection_diff_a_only (void)
|
|||||||
{ NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
{ NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
{ NM_SETTING_IP_CONFIG_ROUTE_TABLE, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP_CONFIG_ROUTE_TABLE, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
|
{ NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
{ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
{ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
||||||
|
@@ -2362,7 +2362,16 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||||||
NMSettingConnection *s_con = NULL;
|
NMSettingConnection *s_con = NULL;
|
||||||
NMSettingWired *s_eth = NULL;
|
NMSettingWired *s_eth = NULL;
|
||||||
NMSettingWireGuard *s_wg = NULL;
|
NMSettingWireGuard *s_wg = NULL;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
NMSettingIPConfig *s_6;
|
||||||
|
NMSettingIPConfig *s_4;
|
||||||
|
};
|
||||||
|
NMSettingIPConfig *s_x[2];
|
||||||
|
} s_ip;
|
||||||
|
int is_ipv4;
|
||||||
guint i;
|
guint i;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
switch (MODE) {
|
switch (MODE) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -2549,6 +2558,89 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||||||
_rndt_wg_peers_assert_equal (s_wg, wg_peers, TRUE, TRUE, FALSE);
|
_rndt_wg_peers_assert_equal (s_wg, wg_peers, TRUE, TRUE, FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
con = nmtst_create_minimal_connection (ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
||||||
|
g_object_set (s_con,
|
||||||
|
NM_SETTING_CONNECTION_INTERFACE_NAME,
|
||||||
|
INTERFACE_NAME,
|
||||||
|
NULL);
|
||||||
|
nmtst_connection_normalize (con);
|
||||||
|
|
||||||
|
s_eth = NM_SETTING_WIRED (nm_connection_get_setting (con, NM_TYPE_SETTING_WIRED));
|
||||||
|
g_assert (NM_IS_SETTING_WIRED (s_eth));
|
||||||
|
|
||||||
|
g_object_set (s_eth,
|
||||||
|
NM_SETTING_WIRED_MTU,
|
||||||
|
ETH_MTU,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
s_ip.s_4 = NM_SETTING_IP_CONFIG (nm_connection_get_setting (con, NM_TYPE_SETTING_IP4_CONFIG));
|
||||||
|
g_assert (NM_IS_SETTING_IP4_CONFIG (s_ip.s_4));
|
||||||
|
|
||||||
|
s_ip.s_6 = NM_SETTING_IP_CONFIG (nm_connection_get_setting (con, NM_TYPE_SETTING_IP6_CONFIG));
|
||||||
|
g_assert (NM_IS_SETTING_IP6_CONFIG (s_ip.s_6));
|
||||||
|
|
||||||
|
for (is_ipv4 = 0; is_ipv4 < 2; is_ipv4++) {
|
||||||
|
g_assert (NM_IS_SETTING_IP_CONFIG (s_ip.s_x[is_ipv4]));
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
char addrstr[NM_UTILS_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL;
|
||||||
|
|
||||||
|
rr = nm_ip_routing_rule_new (is_ipv4 ? AF_INET : AF_INET6);
|
||||||
|
nm_ip_routing_rule_set_priority (rr, i + 1);
|
||||||
|
if (i > 0) {
|
||||||
|
if (is_ipv4)
|
||||||
|
nm_sprintf_buf (addrstr, "192.168.%u.0", i);
|
||||||
|
else
|
||||||
|
nm_sprintf_buf (addrstr, "1:2:3:%x::", 10 + i);
|
||||||
|
nm_ip_routing_rule_set_from (rr, addrstr, is_ipv4 ? 24 + i : 64 + i);
|
||||||
|
}
|
||||||
|
nm_ip_routing_rule_set_table (rr, 1000 + i);
|
||||||
|
|
||||||
|
success = nm_ip_routing_rule_validate (rr, &error);
|
||||||
|
nmtst_assert_success (success, error);
|
||||||
|
|
||||||
|
nm_setting_ip_config_add_routing_rule (s_ip.s_x[is_ipv4], rr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (kf_data_arr,
|
||||||
|
g_strdup_printf ("[connection]\n"
|
||||||
|
"id=%s\n"
|
||||||
|
"uuid=%s\n"
|
||||||
|
"type=ethernet\n"
|
||||||
|
"interface-name=%s\n"
|
||||||
|
"permissions=\n"
|
||||||
|
"\n"
|
||||||
|
"[ethernet]\n"
|
||||||
|
"mac-address-blacklist=\n"
|
||||||
|
"%s" /* mtu */
|
||||||
|
"\n"
|
||||||
|
"[ipv4]\n"
|
||||||
|
"dns-search=\n"
|
||||||
|
"method=auto\n"
|
||||||
|
"routing-rule1=priority 1 from 0.0.0.0/0 table 1000\n"
|
||||||
|
"routing-rule2=priority 2 from 192.168.1.0/25 table 1001\n"
|
||||||
|
"routing-rule3=priority 3 from 192.168.2.0/26 table 1002\n"
|
||||||
|
"\n"
|
||||||
|
"[ipv6]\n"
|
||||||
|
"addr-gen-mode=stable-privacy\n"
|
||||||
|
"dns-search=\n"
|
||||||
|
"method=auto\n"
|
||||||
|
"routing-rule1=priority 1 from ::/0 table 1000\n"
|
||||||
|
"routing-rule2=priority 2 from 1:2:3:b::/65 table 1001\n"
|
||||||
|
"routing-rule3=priority 3 from 1:2:3:c::/66 table 1002\n"
|
||||||
|
"",
|
||||||
|
ID,
|
||||||
|
UUID,
|
||||||
|
INTERFACE_NAME,
|
||||||
|
(ETH_MTU != 0)
|
||||||
|
? nm_sprintf_bufa (100, "mtu=%u\n", ETH_MTU)
|
||||||
|
: ""));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
@@ -2954,6 +3046,7 @@ main (int argc, char **argv)
|
|||||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/0", GINT_TO_POINTER (0), test_roundtrip_conversion);
|
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/0", GINT_TO_POINTER (0), test_roundtrip_conversion);
|
||||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/1", GINT_TO_POINTER (1), test_roundtrip_conversion);
|
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/1", GINT_TO_POINTER (1), test_roundtrip_conversion);
|
||||||
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/2", GINT_TO_POINTER (2), test_roundtrip_conversion);
|
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/2", GINT_TO_POINTER (2), test_roundtrip_conversion);
|
||||||
|
g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/3", GINT_TO_POINTER (3), test_roundtrip_conversion);
|
||||||
|
|
||||||
g_test_add_data_func ("/libnm/settings/routing-rule/1", GINT_TO_POINTER (0), test_routing_rule);
|
g_test_add_data_func ("/libnm/settings/routing-rule/1", GINT_TO_POINTER (0), test_routing_rule);
|
||||||
|
|
||||||
|
@@ -1595,4 +1595,9 @@ global:
|
|||||||
nm_setting_bridge_port_remove_vlan_by_vid;
|
nm_setting_bridge_port_remove_vlan_by_vid;
|
||||||
nm_setting_bridge_remove_vlan;
|
nm_setting_bridge_remove_vlan;
|
||||||
nm_setting_bridge_remove_vlan_by_vid;
|
nm_setting_bridge_remove_vlan_by_vid;
|
||||||
|
nm_setting_ip_config_add_routing_rule;
|
||||||
|
nm_setting_ip_config_clear_routing_rules;
|
||||||
|
nm_setting_ip_config_get_num_routing_rules;
|
||||||
|
nm_setting_ip_config_get_routing_rule;
|
||||||
|
nm_setting_ip_config_remove_routing_rule;
|
||||||
} libnm_1_16_0;
|
} libnm_1_16_0;
|
||||||
|
Reference in New Issue
Block a user