diff options
author | Thomas Haller <thaller@redhat.com> | 2019-03-14 12:04:21 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-03-27 16:23:30 +0100 |
commit | 6e6d1e070ca52c8b4a414f320a3076b94a8613a0 (patch) | |
tree | 398529b68884d7dcda0b39929544bb51b6f2023a | |
parent | 7fb23b0a62a0dfe038622a1559e60c97a6739aa0 (diff) | |
download | NetworkManager-6e6d1e070ca52c8b4a414f320a3076b94a8613a0.tar.gz |
libnm: add API to NMSettingIPConfig for routing rules
-rw-r--r-- | libnm-core/nm-keyfile.c | 112 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-config.c | 351 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-config.h | 17 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 1 | ||||
-rw-r--r-- | libnm-core/tests/test-setting.c | 95 | ||||
-rw-r--r-- | libnm/libnm.ver | 5 |
6 files changed, 578 insertions, 3 deletions
diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index 2b77a84463..a541bd556c 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -541,6 +541,7 @@ typedef struct { typedef enum { BUILD_LIST_TYPE_ADDRESSES, BUILD_LIST_TYPE_ROUTES, + BUILD_LIST_TYPE_ROUTING_RULES, } BuildListType; static int @@ -661,6 +662,12 @@ _build_list_create (GKeyFile *keyfile, else continue; 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: nm_assert_not_reached (); break; @@ -760,6 +767,63 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c } 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 ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) { int addr_family; @@ -1963,6 +2027,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 qdisc_writer (KeyfileWriterInfo *info, NMSetting *setting, const char *key, @@ -2463,6 +2561,13 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { .parser = ip_address_or_route_parser, .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, @@ -2491,6 +2596,13 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { .parser = ip_address_or_route_parser, .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, diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index b4b50e51c1..53d55c57cd 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -3533,6 +3533,7 @@ typedef struct { int dns_priority; GPtrArray *addresses; /* array of NMIPAddress */ GPtrArray *routes; /* array of NMIPRoute */ + GPtrArray *routing_rules; gint64 route_metric; guint32 route_table; 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; } +/*****************************************************************************/ + +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: * @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) { g_set_error (error, NM_CONNECTION_ERROR, @@ -4774,6 +5021,24 @@ compare_property (const NMSettInfoSetting *sett_info, 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, property_idx, setting, @@ -4781,6 +5046,72 @@ compare_property (const NMSettInfoSetting *sett_info, 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 @@ -4813,6 +5144,18 @@ _nm_sett_info_property_override_create_array_ip_config (void) ip_gateway_set, 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; } @@ -5020,6 +5363,8 @@ finalize (GObject *object) g_ptr_array_unref (priv->dns_options); g_ptr_array_unref (priv->addresses); 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); } @@ -5036,8 +5381,10 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass) object_class->set_property = set_property; object_class->finalize = finalize; - setting_class->verify = verify; - setting_class->compare_property = compare_property; + setting_class->verify = verify; + setting_class->compare_property = compare_property; + setting_class->duplicate_copy_properties = duplicate_copy_properties; + setting_class->enumerate_values = enumerate_values; /** * NMSettingIPConfig:method: diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 0522ea1991..09b80f72a9 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -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_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_NDOTS "ndots" #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 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_dns (NMSettingIPConfig *setting); diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 6d5eeb2810..98e5837176 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -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_ROUTE_METRIC, 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_DNS, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A }, diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index f9d87eb6c2..bd6b4e7fd2 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -2362,7 +2362,16 @@ test_roundtrip_conversion (gconstpointer test_data) NMSettingConnection *s_con = NULL; NMSettingWired *s_eth = NULL; NMSettingWireGuard *s_wg = NULL; + union { + struct { + NMSettingIPConfig *s_6; + NMSettingIPConfig *s_4; + }; + NMSettingIPConfig *s_x[2]; + } s_ip; + int is_ipv4; guint i; + gboolean success; switch (MODE) { case 0: @@ -2549,6 +2558,89 @@ test_roundtrip_conversion (gconstpointer test_data) _rndt_wg_peers_assert_equal (s_wg, wg_peers, TRUE, TRUE, FALSE); 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: g_assert_not_reached (); } @@ -2951,9 +3043,10 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config); #endif - 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/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); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 20adc91c78..ac8c7b97cf 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1595,4 +1595,9 @@ global: nm_setting_bridge_port_remove_vlan_by_vid; nm_setting_bridge_remove_vlan; 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; |