mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-19 02:00:45 +02:00
libnm,core: merge branch 'th/routing-rule-pt2'
https://github.com/NetworkManager/NetworkManager/pull/321
This commit is contained in:
commit
7680014732
30 changed files with 5004 additions and 821 deletions
|
|
@ -2729,6 +2729,7 @@ EXTRA_DIST += \
|
|||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected \
|
||||
src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected \
|
||||
|
|
|
|||
|
|
@ -543,13 +543,18 @@ nmc_setting_set_property (NMClient *client,
|
|||
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
g_return_val_if_fail (NM_IN_SET (modifier, '\0', '-', '+'), FALSE);
|
||||
g_return_val_if_fail (value || modifier == '\0', FALSE);
|
||||
|
||||
if (!(property_info = nm_meta_property_info_find_by_setting (setting, prop)))
|
||||
goto out_fail_read_only;
|
||||
if (!property_info->property_type->set_fcn)
|
||||
goto out_fail_read_only;
|
||||
|
||||
if ( NM_IN_SET (modifier, '+', '-')
|
||||
&& !value) {
|
||||
/* nothing to do. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ( modifier == '-'
|
||||
&& !property_info->property_type->set_supports_remove) {
|
||||
/* The property is a plain property. It does not support '-'.
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ _value_str_as_index_list (const char *value, gsize *out_len)
|
|||
typedef enum {
|
||||
VALUE_STRSPLIT_MODE_STRIPPED,
|
||||
VALUE_STRSPLIT_MODE_OBJLIST,
|
||||
VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE,
|
||||
VALUE_STRSPLIT_MODE_MULTILIST,
|
||||
VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE,
|
||||
} ValueStrsplitMode;
|
||||
|
|
@ -201,6 +202,9 @@ _value_strsplit (const char *value,
|
|||
case VALUE_STRSPLIT_MODE_OBJLIST:
|
||||
strv = nm_utils_strsplit_set (value, ",", FALSE);
|
||||
break;
|
||||
case VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE:
|
||||
strv = nm_utils_strsplit_set (value, ",", TRUE);
|
||||
break;
|
||||
case VALUE_STRSPLIT_MODE_MULTILIST:
|
||||
strv = nm_utils_strsplit_set (value, " \t,", FALSE);
|
||||
break;
|
||||
|
|
@ -227,6 +231,8 @@ _value_strsplit (const char *value,
|
|||
|
||||
if (split_mode == VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE)
|
||||
_nm_utils_unescape_plain ((char *) s, MULTILIST_WITH_ESCAPE_CHARS, TRUE);
|
||||
else if (split_mode == VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE)
|
||||
_nm_utils_unescape_plain ((char *) s, ",", TRUE);
|
||||
else
|
||||
g_strchomp ((char *) s);
|
||||
|
||||
|
|
@ -1876,7 +1882,7 @@ _set_fcn_multilist (ARGS_SET_FCN)
|
|||
}
|
||||
|
||||
strv = _value_strsplit (value,
|
||||
property_info->property_typ_data->subtype.multilist.with_escaped_spaces
|
||||
property_info->property_typ_data->subtype.multilist.strsplit_with_escape
|
||||
? VALUE_STRSPLIT_MODE_MULTILIST_WITH_ESCAPE
|
||||
: VALUE_STRSPLIT_MODE_MULTILIST,
|
||||
&nstrv);
|
||||
|
|
@ -3049,6 +3055,10 @@ _get_fcn_objlist (ARGS_GET_FCN)
|
|||
num = property_info->property_typ_data->subtype.objlist.get_num_fcn (setting);
|
||||
|
||||
for (idx = 0; idx < num; idx++) {
|
||||
#if NM_MORE_ASSERTS
|
||||
gsize start_offset;
|
||||
#endif
|
||||
|
||||
if (!str)
|
||||
str = g_string_new (NULL);
|
||||
else if (str->len > 0) {
|
||||
|
|
@ -3059,10 +3069,32 @@ _get_fcn_objlist (ARGS_GET_FCN)
|
|||
g_string_append (str, ", ");
|
||||
}
|
||||
|
||||
#if NM_MORE_ASSERTS
|
||||
start_offset = str->len;
|
||||
#endif
|
||||
|
||||
property_info->property_typ_data->subtype.objlist.obj_to_str_fcn (get_type,
|
||||
setting,
|
||||
idx,
|
||||
str);
|
||||
|
||||
#if NM_MORE_ASSERTS
|
||||
nm_assert (start_offset < str->len);
|
||||
if ( property_info->property_typ_data->subtype.objlist.strsplit_with_escape
|
||||
&& get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) {
|
||||
/* if the strsplit is done with VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE, then the appended
|
||||
* value must have no unescaped ','. */
|
||||
for (; start_offset < str->len; ) {
|
||||
if (str->str[start_offset] == '\\') {
|
||||
start_offset++;
|
||||
nm_assert (start_offset < str->len);
|
||||
nm_assert (!NM_IN_SET (str->str[start_offset], '\0'));
|
||||
} else
|
||||
nm_assert (!NM_IN_SET (str->str[start_offset], '\0', ','));
|
||||
start_offset++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NM_SET_OUT (out_is_default, num == 0);
|
||||
|
|
@ -3237,7 +3269,9 @@ _set_fcn_objlist (ARGS_SET_FCN)
|
|||
}
|
||||
|
||||
strv = _value_strsplit (value,
|
||||
VALUE_STRSPLIT_MODE_OBJLIST,
|
||||
property_info->property_typ_data->subtype.objlist.strsplit_with_escape
|
||||
? VALUE_STRSPLIT_MODE_OBJLIST_WITH_ESCAPE
|
||||
: VALUE_STRSPLIT_MODE_OBJLIST,
|
||||
&nstrv);
|
||||
|
||||
if (_SET_FCN_DO_SET_ALL (modifier, value)) {
|
||||
|
|
@ -3335,6 +3369,65 @@ _is_default_func_ip_config_dns_options (NMSetting *setting)
|
|||
&& !nm_setting_ip_config_get_num_dns_options (NM_SETTING_IP_CONFIG (setting));
|
||||
}
|
||||
|
||||
static void
|
||||
_objlist_obj_to_str_fcn_ip_config_routing_rules (NMMetaAccessorGetType get_type,
|
||||
NMSetting *setting,
|
||||
guint idx,
|
||||
GString *str)
|
||||
{
|
||||
NMIPRoutingRule *rule;
|
||||
gs_free char *s = NULL;
|
||||
|
||||
rule = nm_setting_ip_config_get_routing_rule (NM_SETTING_IP_CONFIG (setting), idx);
|
||||
s = nm_ip_routing_rule_to_string (rule,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE,
|
||||
NULL,
|
||||
NULL);
|
||||
if (s)
|
||||
g_string_append (str, s);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_objlist_set_fcn_ip_config_routing_rules (NMSetting *setting,
|
||||
gboolean do_add,
|
||||
const char *str,
|
||||
GError **error)
|
||||
{
|
||||
NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL;
|
||||
guint i, n;
|
||||
|
||||
rule = nm_ip_routing_rule_from_string (str,
|
||||
( NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| ( NM_IS_SETTING_IP4_CONFIG (setting)
|
||||
? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET
|
||||
: NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6)),
|
||||
NULL,
|
||||
error);
|
||||
if (!rule)
|
||||
return FALSE;
|
||||
|
||||
/* also for @do_add, we first always search whether such a rule already exist
|
||||
* and remove the first occurance.
|
||||
*
|
||||
* The effect is, that we don't add multiple times the same rule,
|
||||
* and that if the rule already exists, it gets moved to the end (append).
|
||||
*/
|
||||
n = nm_setting_ip_config_get_num_routing_rules (s_ip);
|
||||
for (i = 0; i < n; i++) {
|
||||
NMIPRoutingRule *rr;
|
||||
|
||||
rr = nm_setting_ip_config_get_routing_rule (s_ip, i);
|
||||
if (nm_ip_routing_rule_cmp (rule, rr) == 0) {
|
||||
nm_setting_ip_config_remove_routing_rule (s_ip, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (do_add)
|
||||
nm_setting_ip_config_add_routing_rule (s_ip, rule);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gconstpointer
|
||||
_get_fcn_match_interface_name (ARGS_GET_FCN)
|
||||
{
|
||||
|
|
@ -5549,6 +5642,23 @@ static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = {
|
|||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTING_RULES, NULL,
|
||||
.describe_message =
|
||||
N_("Enter a list of IPv4 routing rules formatted as:\n"
|
||||
" priority [prio] [from [src]] [to [dst]], ,...\n"
|
||||
"\n"),
|
||||
.property_type = &_pt_objlist,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
|
||||
PROPERTY_TYP_DATA_SUBTYPE (objlist,
|
||||
.get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingIPConfig, nm_setting_ip_config_get_num_routing_rules),
|
||||
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingIPConfig, nm_setting_ip_config_clear_routing_rules),
|
||||
.obj_to_str_fcn = _objlist_obj_to_str_fcn_ip_config_routing_rules,
|
||||
.set_fcn = _objlist_set_fcn_ip_config_routing_rules,
|
||||
.remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingIPConfig, nm_setting_ip_config_remove_routing_rule),
|
||||
.strsplit_with_escape = TRUE,
|
||||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
|
|
@ -5740,6 +5850,23 @@ static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = {
|
|||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTING_RULES, NULL,
|
||||
.describe_message =
|
||||
N_("Enter a list of IPv6 routing rules formatted as:\n"
|
||||
" priority [prio] [from [src]] [to [dst]], ,...\n"
|
||||
"\n"),
|
||||
.property_type = &_pt_objlist,
|
||||
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
|
||||
PROPERTY_TYP_DATA_SUBTYPE (objlist,
|
||||
.get_num_fcn = OBJLIST_GET_NUM_FCN (NMSettingIPConfig, nm_setting_ip_config_get_num_routing_rules),
|
||||
.clear_all_fcn = OBJLIST_CLEAR_ALL_FCN (NMSettingIPConfig, nm_setting_ip_config_clear_routing_rules),
|
||||
.obj_to_str_fcn = _objlist_obj_to_str_fcn_ip_config_routing_rules,
|
||||
.set_fcn = _objlist_set_fcn_ip_config_routing_rules,
|
||||
.remove_by_idx_fcn_u = OBJLIST_REMOVE_BY_IDX_FCN_U (NMSettingIPConfig, nm_setting_ip_config_remove_routing_rule),
|
||||
.strsplit_with_escape = TRUE,
|
||||
),
|
||||
),
|
||||
),
|
||||
PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
|
|
@ -5983,7 +6110,7 @@ static const NMMetaPropertyInfo *const property_infos_MATCH[] = {
|
|||
.add2_fcn = MULTILIST_ADD2_FCN (NMSettingMatch, nm_setting_match_add_interface_name),
|
||||
.remove_by_idx_fcn_s = MULTILIST_REMOVE_BY_IDX_FCN_S (NMSettingMatch, nm_setting_match_remove_interface_name),
|
||||
.remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingMatch, nm_setting_match_remove_interface_name_by_value),
|
||||
.with_escaped_spaces = TRUE,
|
||||
.strsplit_with_escape = TRUE,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -280,9 +280,7 @@ struct _NMMetaPropertyTypData {
|
|||
void (*remove_by_idx_fcn_u) (NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s) (NMSetting *setting, int idx);
|
||||
gboolean (*remove_by_value_fcn) (NMSetting *setting, const char *item);
|
||||
|
||||
/* if true, separate the list by space and allow backslash escaping. */
|
||||
bool with_escaped_spaces:1;
|
||||
bool strsplit_with_escape:1;
|
||||
} multilist;
|
||||
struct {
|
||||
guint (*get_num_fcn) (NMSetting *setting);
|
||||
|
|
@ -298,6 +296,7 @@ struct _NMMetaPropertyTypData {
|
|||
void (*remove_by_idx_fcn_u) (NMSetting *setting, guint idx);
|
||||
void (*remove_by_idx_fcn_s) (NMSetting *setting, int idx);
|
||||
bool delimit_pretty_with_semicolon:1;
|
||||
bool strsplit_with_escape:1;
|
||||
} objlist;
|
||||
struct {
|
||||
gboolean (*set_fcn) (NMSetting *setting,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -250,6 +250,8 @@ guint nm_setting_ethtool_init_features (NMSettingEthtool *setting,
|
|||
guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length);
|
||||
const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboolean upper_case, char *buf, gsize buf_len);
|
||||
|
||||
gboolean nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name);
|
||||
|
||||
GSList * _nm_utils_hash_values_to_slist (GHashTable *hash);
|
||||
|
||||
GHashTable *_nm_utils_copy_strdict (GHashTable *strdict);
|
||||
|
|
@ -611,6 +613,47 @@ void _nm_wireguard_peer_set_public_key_bin (NMWireGuardPeer *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMIPAddr *nm_ip_routing_rule_get_from_bin (const NMIPRoutingRule *self);
|
||||
void nm_ip_routing_rule_set_from_bin (NMIPRoutingRule *self,
|
||||
gconstpointer from,
|
||||
guint8 len);
|
||||
|
||||
const NMIPAddr *nm_ip_routing_rule_get_to_bin (const NMIPRoutingRule *self);
|
||||
void nm_ip_routing_rule_set_to_bin (NMIPRoutingRule *self,
|
||||
gconstpointer to,
|
||||
guint8 len);
|
||||
|
||||
gboolean nm_ip_routing_rule_get_xifname_bin (const NMIPRoutingRule *self,
|
||||
gboolean iif /* or else oif */,
|
||||
char out_xifname[static 16]);
|
||||
|
||||
#define NM_IP_ROUTING_RULE_ATTR_ACTION "action"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_DPORT_END "dport-end"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_DPORT_START "dport-start"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_FAMILY "family"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_FROM "from"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_FROM_LEN "from-len"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_FWMARK "fwmark"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_FWMASK "fwmask"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_IIFNAME "iifname"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_INVERT "invert"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_IPPROTO "ipproto"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_OIFNAME "oifname"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_PRIORITY "priority"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_SPORT_END "sport-end"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_SPORT_START "sport-start"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_TABLE "table"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_TO "to"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_TOS "tos"
|
||||
#define NM_IP_ROUTING_RULE_ATTR_TO_LEN "to-len"
|
||||
|
||||
NMIPRoutingRule *nm_ip_routing_rule_from_dbus (GVariant *variant,
|
||||
gboolean strict,
|
||||
GError **error);
|
||||
GVariant *nm_ip_routing_rule_to_dbus (const NMIPRoutingRule *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMSettInfoSetting NMSettInfoSetting;
|
||||
typedef struct _NMSettInfoProperty NMSettInfoProperty;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _ParseInfoProperty ParseInfoProperty;
|
||||
|
||||
typedef struct {
|
||||
NMConnection *connection;
|
||||
GKeyFile *keyfile;
|
||||
|
|
@ -534,13 +536,19 @@ typedef struct {
|
|||
const char *s_key;
|
||||
gint32 key_idx;
|
||||
gint8 key_type;
|
||||
} IPAddrRouteBuildListData;
|
||||
} BuildListData;
|
||||
|
||||
typedef enum {
|
||||
BUILD_LIST_TYPE_ADDRESSES,
|
||||
BUILD_LIST_TYPE_ROUTES,
|
||||
BUILD_LIST_TYPE_ROUTING_RULES,
|
||||
} BuildListType;
|
||||
|
||||
static int
|
||||
_ip_addrroute_build_lst_data_cmp (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
|
||||
_build_list_data_cmp (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
|
||||
{
|
||||
const IPAddrRouteBuildListData *a = p_a;
|
||||
const IPAddrRouteBuildListData *b = p_b;
|
||||
const BuildListData *a = p_a;
|
||||
const BuildListData *b = p_b;
|
||||
|
||||
NM_CMP_FIELD (a, b, key_idx);
|
||||
NM_CMP_FIELD (a, b, key_type);
|
||||
|
|
@ -549,10 +557,25 @@ _ip_addrroute_build_lst_data_cmp (gconstpointer p_a, gconstpointer p_b, gpointer
|
|||
}
|
||||
|
||||
static gboolean
|
||||
ip_addrroute_match_key_w_name_ (const char *key,
|
||||
const char *base_name,
|
||||
gsize base_name_l,
|
||||
gint32 *out_key_idx)
|
||||
_build_list_data_is_shadowed (const BuildListData *build_list,
|
||||
gsize build_list_len,
|
||||
gsize idx)
|
||||
{
|
||||
/* the keyfile contains duplicate keys, which are both returned
|
||||
* by g_key_file_get_keys() (WHY??).
|
||||
*
|
||||
* Skip the earlier one. */
|
||||
return idx + 1 < build_list_len
|
||||
&& build_list[idx].key_idx == build_list[idx + 1].key_idx
|
||||
&& build_list[idx].key_type == build_list[idx + 1].key_type
|
||||
&& nm_streq (build_list[idx].s_key, build_list[idx + 1].s_key);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_build_list_match_key_w_name_impl (const char *key,
|
||||
const char *base_name,
|
||||
gsize base_name_l,
|
||||
gint32 *out_key_idx)
|
||||
{
|
||||
gint64 v;
|
||||
|
||||
|
|
@ -595,31 +618,85 @@ ip_addrroute_match_key_w_name_ (const char *key,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip_addrroute_match_key (const char *key,
|
||||
gboolean is_routes,
|
||||
gint32 *out_key_idx,
|
||||
gint8 *out_key_type)
|
||||
{
|
||||
#define ip_addrroute_match_key_w_name(key, base_name, out_key_idx) \
|
||||
ip_addrroute_match_key_w_name_ (key, base_name, NM_STRLEN (base_name), out_key_idx)
|
||||
#define _build_list_match_key_w_name(key, base_name, out_key_idx) \
|
||||
_build_list_match_key_w_name_impl (key, base_name, NM_STRLEN (base_name), out_key_idx)
|
||||
|
||||
if (is_routes) {
|
||||
if (ip_addrroute_match_key_w_name (key, "route", out_key_idx))
|
||||
NM_SET_OUT (out_key_type, 0);
|
||||
else if (ip_addrroute_match_key_w_name (key, "routes", out_key_idx))
|
||||
NM_SET_OUT (out_key_type, 1);
|
||||
else
|
||||
return FALSE;
|
||||
} else {
|
||||
if (ip_addrroute_match_key_w_name (key, "address", out_key_idx))
|
||||
NM_SET_OUT (out_key_type, 0);
|
||||
else if (ip_addrroute_match_key_w_name (key, "addresses", out_key_idx))
|
||||
NM_SET_OUT (out_key_type, 1);
|
||||
else
|
||||
return FALSE;
|
||||
static BuildListData *
|
||||
_build_list_create (GKeyFile *keyfile,
|
||||
const char *group_name,
|
||||
BuildListType build_list_type,
|
||||
gsize *out_build_list_len,
|
||||
char ***out_keys_strv)
|
||||
{
|
||||
gs_strfreev char **keys = NULL;
|
||||
gsize i_keys, n_keys;
|
||||
gs_free BuildListData *build_list = NULL;
|
||||
gsize build_list_len = 0;
|
||||
|
||||
nm_assert (out_build_list_len && *out_build_list_len == 0);
|
||||
nm_assert (out_keys_strv && !*out_keys_strv);
|
||||
|
||||
keys = nm_keyfile_plugin_kf_get_keys (keyfile, group_name, &n_keys, NULL);
|
||||
if (n_keys == 0)
|
||||
return NULL;
|
||||
|
||||
for (i_keys = 0; i_keys < n_keys; i_keys++) {
|
||||
const char *s_key = keys[i_keys];
|
||||
gint32 key_idx;
|
||||
gint8 key_type;
|
||||
|
||||
switch (build_list_type) {
|
||||
case BUILD_LIST_TYPE_ROUTES:
|
||||
if (_build_list_match_key_w_name (s_key, "route", &key_idx))
|
||||
key_type = 0;
|
||||
else if (_build_list_match_key_w_name (s_key, "routes", &key_idx))
|
||||
key_type = 1;
|
||||
else
|
||||
continue;
|
||||
break;
|
||||
case BUILD_LIST_TYPE_ADDRESSES:
|
||||
if (_build_list_match_key_w_name (s_key, "address", &key_idx))
|
||||
key_type = 0;
|
||||
else if (_build_list_match_key_w_name (s_key, "addresses", &key_idx))
|
||||
key_type = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!build_list))
|
||||
build_list = g_new (BuildListData, n_keys - i_keys);
|
||||
|
||||
build_list[build_list_len++] = (BuildListData) {
|
||||
.s_key = s_key,
|
||||
.key_idx = key_idx,
|
||||
.key_type = key_type,
|
||||
};
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
if (build_list_len == 0)
|
||||
return NULL;
|
||||
|
||||
if (build_list_len > 1) {
|
||||
g_qsort_with_data (build_list,
|
||||
build_list_len,
|
||||
sizeof (BuildListData),
|
||||
_build_list_data_cmp,
|
||||
NULL);
|
||||
}
|
||||
|
||||
*out_build_list_len = build_list_len;
|
||||
*out_keys_strv = g_steal_pointer (&keys);
|
||||
return g_steal_pointer (&build_list);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -631,64 +708,35 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||
gs_free char *gateway = NULL;
|
||||
gs_unref_ptrarray GPtrArray *list = NULL;
|
||||
gs_strfreev char **keys = NULL;
|
||||
gsize i_keys, n_keys;
|
||||
gs_free IPAddrRouteBuildListData *build_list = NULL;
|
||||
gs_free BuildListData *build_list = NULL;
|
||||
gsize i_build_list, build_list_len = 0;
|
||||
|
||||
keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL);
|
||||
if (n_keys == 0)
|
||||
build_list = _build_list_create (info->keyfile,
|
||||
setting_name,
|
||||
is_routes
|
||||
? BUILD_LIST_TYPE_ROUTES
|
||||
: BUILD_LIST_TYPE_ADDRESSES,
|
||||
&build_list_len,
|
||||
&keys);
|
||||
if (!build_list)
|
||||
return;
|
||||
|
||||
/* first create a list of all relevant keys, and sort them. */
|
||||
for (i_keys = 0; i_keys < n_keys; i_keys++) {
|
||||
const char *s_key = keys[i_keys];
|
||||
gint32 key_idx;
|
||||
gint8 key_type;
|
||||
|
||||
if (!ip_addrroute_match_key (s_key, is_routes, &key_idx, &key_type))
|
||||
continue;
|
||||
|
||||
if (G_UNLIKELY (!build_list))
|
||||
build_list = g_new (IPAddrRouteBuildListData, n_keys - i_keys);
|
||||
|
||||
build_list[build_list_len].s_key = s_key;
|
||||
build_list[build_list_len].key_idx = key_idx;
|
||||
build_list[build_list_len].key_type = key_type;
|
||||
build_list_len++;
|
||||
}
|
||||
|
||||
if (build_list_len == 0)
|
||||
return;
|
||||
|
||||
g_qsort_with_data (build_list,
|
||||
build_list_len,
|
||||
sizeof (IPAddrRouteBuildListData),
|
||||
_ip_addrroute_build_lst_data_cmp,
|
||||
NULL);
|
||||
|
||||
list = g_ptr_array_new_with_free_func (is_routes
|
||||
? (GDestroyNotify) nm_ip_route_unref
|
||||
: (GDestroyNotify) nm_ip_address_unref);
|
||||
|
||||
for (i_build_list = 0; i_build_list < build_list_len; i_build_list++) {
|
||||
const IPAddrRouteBuildListData *build_data = &build_list[i_build_list];
|
||||
const char *s_key;
|
||||
gpointer item;
|
||||
|
||||
if ( i_build_list + 1 < build_list_len
|
||||
&& build_data->key_idx == build_data[1].key_idx
|
||||
&& build_data->key_type == build_data[1].key_type
|
||||
&& nm_streq (build_data->s_key, build_data[1].s_key)) {
|
||||
/* the keyfile contains duplicate keys, which are both returned
|
||||
* by g_key_file_get_keys() (WHY??).
|
||||
*
|
||||
* Skip the earlier one. */
|
||||
if (_build_list_data_is_shadowed (build_list, build_list_len, i_build_list))
|
||||
continue;
|
||||
}
|
||||
|
||||
s_key = build_list[i_build_list].s_key;
|
||||
item = read_one_ip_address_or_route (info,
|
||||
setting_key,
|
||||
setting_name,
|
||||
build_data->s_key,
|
||||
s_key,
|
||||
is_ipv6,
|
||||
is_routes,
|
||||
gateway ? NULL : &gateway,
|
||||
|
|
@ -696,7 +744,7 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||
if (item && is_routes) {
|
||||
char options_key[128];
|
||||
|
||||
nm_sprintf_buf (options_key, "%s_options", build_data->s_key);
|
||||
nm_sprintf_buf (options_key, "%s_options", s_key);
|
||||
fill_route_attributes (info->keyfile,
|
||||
item,
|
||||
setting_name,
|
||||
|
|
@ -718,6 +766,63 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
|
|||
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
|
||||
ip_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
|
|
@ -1921,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
|
||||
qdisc_writer (KeyfileWriterInfo *info,
|
||||
NMSetting *setting,
|
||||
|
|
@ -2232,24 +2371,40 @@ cert_writer (KeyfileWriterInfo *info,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
struct _ParseInfoProperty {
|
||||
const char *property_name;
|
||||
void (*parser) (KeyfileReaderInfo *info,
|
||||
NMSetting *setting,
|
||||
const char *key);
|
||||
void (*writer) (KeyfileWriterInfo *info,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value);
|
||||
union {
|
||||
void (*parser) (KeyfileReaderInfo *info,
|
||||
NMSetting *setting,
|
||||
const char *key);
|
||||
void (*parser_full) (KeyfileReaderInfo *info,
|
||||
const NMMetaSettingInfo *setting_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
const ParseInfoProperty *pip,
|
||||
NMSetting *setting);
|
||||
};
|
||||
union {
|
||||
void (*writer) (KeyfileWriterInfo *info,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value);
|
||||
void (*writer_full) (KeyfileWriterInfo *info,
|
||||
const NMMetaSettingInfo *setting_info,
|
||||
const NMSettInfoProperty *property_info,
|
||||
const ParseInfoProperty *pip,
|
||||
NMSetting *setting);
|
||||
};
|
||||
bool parser_skip;
|
||||
bool parser_no_check_key:1;
|
||||
bool writer_skip:1;
|
||||
bool has_writer_full:1;
|
||||
bool has_parser_full:1;
|
||||
|
||||
/* usually, we skip to write values that have their
|
||||
* default value. By setting this flag to TRUE, also
|
||||
* default values are written. */
|
||||
bool writer_persist_default:1;
|
||||
} ParseInfoProperty;
|
||||
};
|
||||
|
||||
#define PARSE_INFO_PROPERTY(_property_name, ...) \
|
||||
(&((const ParseInfoProperty) { \
|
||||
|
|
@ -2406,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,
|
||||
|
|
@ -2434,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,
|
||||
|
|
@ -2612,7 +2781,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
|
|||
static const ParseInfoProperty *
|
||||
_parse_info_find (NMSetting *setting,
|
||||
const char *property_name,
|
||||
const char **out_setting_name)
|
||||
const NMMetaSettingInfo **out_setting_info)
|
||||
{
|
||||
const NMMetaSettingInfo *setting_info;
|
||||
const ParseInfoSetting *pis;
|
||||
|
|
@ -2651,11 +2820,13 @@ _parse_info_find (NMSetting *setting,
|
|||
if ( !NM_IS_SETTING (setting)
|
||||
|| !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) {
|
||||
/* handle invalid setting objects gracefully. */
|
||||
*out_setting_name = NULL;
|
||||
*out_setting_info = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_setting_name = setting_info->setting_name;
|
||||
nm_assert (setting_info->setting_name);
|
||||
|
||||
*out_setting_info = setting_info;
|
||||
|
||||
if ((pis = parse_infos[setting_info->meta_type])) {
|
||||
G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0);
|
||||
|
|
@ -2682,32 +2853,42 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
{
|
||||
GKeyFile *keyfile = info->keyfile;
|
||||
gs_free_error GError *err = NULL;
|
||||
const NMMetaSettingInfo *setting_info;
|
||||
const ParseInfoProperty *pip;
|
||||
gs_free char *tmp_str = NULL;
|
||||
const char *setting_name;
|
||||
const char *key;
|
||||
GType type;
|
||||
guint64 u64;
|
||||
gint64 i64;
|
||||
|
||||
nm_assert (!info->error);
|
||||
nm_assert ( !property_info->param_spec
|
||||
|| nm_streq (property_info->param_spec->name, property_info->name));
|
||||
|
||||
key = property_info->name;
|
||||
|
||||
pip = _parse_info_find (setting, key, &setting_info);
|
||||
|
||||
nm_assert (setting_info);
|
||||
|
||||
if (!pip) {
|
||||
if (nm_streq (key, NM_SETTING_NAME))
|
||||
return;
|
||||
if (!property_info->param_spec)
|
||||
return;
|
||||
if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE)
|
||||
return;
|
||||
} else {
|
||||
if (pip->parser_skip)
|
||||
return;
|
||||
if (pip->has_parser_full) {
|
||||
pip->parser_full (info, setting_info, property_info, pip, setting);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nm_assert (property_info->param_spec);
|
||||
|
||||
if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE)
|
||||
return;
|
||||
|
||||
key = property_info->param_spec->name;
|
||||
|
||||
pip = _parse_info_find (setting, key, &setting_name);
|
||||
|
||||
nm_assert (setting_name);
|
||||
|
||||
if ( !pip
|
||||
&& nm_streq (key, NM_SETTING_NAME))
|
||||
return;
|
||||
|
||||
if (pip && pip->parser_skip)
|
||||
return;
|
||||
nm_assert ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE);
|
||||
|
||||
/* Check for the exact key in the GKeyFile if required. Most setting
|
||||
* properties map 1:1 to a key in the GKeyFile, but for those properties
|
||||
|
|
@ -2715,7 +2896,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
* encoded by the setting property, this won't be true.
|
||||
*/
|
||||
if ( (!pip || !pip->parser_no_check_key)
|
||||
&& !nm_keyfile_plugin_kf_has_key (keyfile, setting_name, key, &err)) {
|
||||
&& !nm_keyfile_plugin_kf_has_key (keyfile, setting_info->setting_name, key, &err)) {
|
||||
/* Key doesn't exist or an error occurred, thus nothing to do. */
|
||||
if (err) {
|
||||
if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
|
|
@ -2726,7 +2907,8 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
return;
|
||||
}
|
||||
|
||||
if (pip && pip->parser) {
|
||||
if ( pip
|
||||
&& pip->parser) {
|
||||
pip->parser (info, setting, key);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2736,11 +2918,11 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
if (type == G_TYPE_STRING) {
|
||||
gs_free char *str_val = NULL;
|
||||
|
||||
str_val = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, &err);
|
||||
str_val = nm_keyfile_plugin_kf_get_string (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err)
|
||||
nm_g_object_set_property_string_take (G_OBJECT (setting), key, g_steal_pointer (&str_val), &err);
|
||||
} else if (type == G_TYPE_UINT) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64);
|
||||
if ( u64 == G_MAXUINT64
|
||||
|
|
@ -2751,7 +2933,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
nm_g_object_set_property_uint (G_OBJECT (setting), key, u64, &err);
|
||||
}
|
||||
} else if (type == G_TYPE_INT) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT, G_MAXINT, G_MININT64);
|
||||
if ( i64 == G_MININT64
|
||||
|
|
@ -2764,11 +2946,11 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
} else if (type == G_TYPE_BOOLEAN) {
|
||||
gboolean bool_val;
|
||||
|
||||
bool_val = nm_keyfile_plugin_kf_get_boolean (keyfile, setting_name, key, &err);
|
||||
bool_val = nm_keyfile_plugin_kf_get_boolean (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err)
|
||||
nm_g_object_set_property_boolean (G_OBJECT (setting), key, bool_val, &err);
|
||||
} else if (type == G_TYPE_CHAR) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
/* As documented by glib, G_TYPE_CHAR is really a (signed!) gint8. */
|
||||
i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT8, G_MAXINT8, G_MININT64);
|
||||
|
|
@ -2780,7 +2962,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
nm_g_object_set_property_char (G_OBJECT (setting), key, i64, &err);
|
||||
}
|
||||
} else if (type == G_TYPE_UINT64) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT64, G_MAXUINT64);
|
||||
if ( u64 == G_MAXUINT64
|
||||
|
|
@ -2791,7 +2973,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
nm_g_object_set_property_uint64 (G_OBJECT (setting), key, u64, &err);
|
||||
}
|
||||
} else if (type == G_TYPE_INT64) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT64, G_MAXINT64, G_MAXINT64);
|
||||
if ( i64 == G_MAXINT64
|
||||
|
|
@ -2809,7 +2991,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
int i;
|
||||
gboolean already_warned = FALSE;
|
||||
|
||||
tmp = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_name, key, &length, NULL);
|
||||
tmp = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_info->setting_name, key, &length, NULL);
|
||||
|
||||
array = g_byte_array_sized_new (length);
|
||||
for (i = 0; i < length; i++) {
|
||||
|
|
@ -2836,14 +3018,14 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
gs_strfreev char **sa = NULL;
|
||||
gsize length;
|
||||
|
||||
sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL);
|
||||
sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_info->setting_name, key, &length, NULL);
|
||||
g_object_set (setting, key, sa, NULL);
|
||||
} else if (type == G_TYPE_HASH_TABLE) {
|
||||
read_hash_of_string (keyfile, setting, key);
|
||||
} else if (type == G_TYPE_ARRAY) {
|
||||
read_array_of_uint (keyfile, setting, key);
|
||||
} else if (G_TYPE_IS_FLAGS (type)) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
u64 = _nm_utils_ascii_str_to_uint64 (tmp_str, 0, 0, G_MAXUINT, G_MAXUINT64);
|
||||
if ( u64 == G_MAXUINT64
|
||||
|
|
@ -2854,7 +3036,7 @@ read_one_setting_value (KeyfileReaderInfo *info,
|
|||
nm_g_object_set_property_flags (G_OBJECT (setting), key, type, u64, &err);
|
||||
}
|
||||
} else if (G_TYPE_IS_ENUM (type)) {
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_name, key, &err);
|
||||
tmp_str = nm_keyfile_plugin_kf_get_value (keyfile, setting_info->setting_name, key, &err);
|
||||
if (!err) {
|
||||
i64 = _nm_utils_ascii_str_to_int64 (tmp_str, 0, G_MININT, G_MAXINT, G_MAXINT64);
|
||||
if ( i64 == G_MAXINT64
|
||||
|
|
@ -2976,13 +3158,11 @@ _read_setting (KeyfileReaderInfo *info)
|
|||
}
|
||||
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
|
||||
|
||||
if (property_info->param_spec) {
|
||||
read_one_setting_value (info, setting, property_info);
|
||||
if (info->error)
|
||||
goto out;
|
||||
}
|
||||
read_one_setting_value (info,
|
||||
setting,
|
||||
&sett_info->property_infos[i]);
|
||||
if (info->error)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -3291,40 +3471,47 @@ write_setting_value (KeyfileWriterInfo *info,
|
|||
NMSetting *setting,
|
||||
const NMSettInfoProperty *property_info)
|
||||
{
|
||||
const NMMetaSettingInfo *setting_info;
|
||||
const ParseInfoProperty *pip;
|
||||
const char *setting_name;
|
||||
const char *key;
|
||||
char numstr[64];
|
||||
GValue value;
|
||||
GType type;
|
||||
|
||||
nm_assert (!info->error);
|
||||
nm_assert ( !property_info->param_spec
|
||||
|| nm_streq (property_info->param_spec->name, property_info->name));
|
||||
|
||||
if (!property_info->param_spec)
|
||||
return;
|
||||
key = property_info->name;
|
||||
|
||||
key = property_info->param_spec->name;
|
||||
pip = _parse_info_find (setting, key, &setting_info);
|
||||
|
||||
pip = _parse_info_find (setting, key, &setting_name);
|
||||
|
||||
if (!setting_name) {
|
||||
/* the setting type is unknown. That is highly unexpected
|
||||
* (and as this is currently only called from NetworkManager
|
||||
* daemon, not possible).
|
||||
*
|
||||
* Still, handle it gracefully, because later keyfile writer will become
|
||||
* public API of libnm, where @setting is (untrusted) user input.
|
||||
*
|
||||
* Gracefully here just means: ignore the setting. */
|
||||
return;
|
||||
if (!pip) {
|
||||
if (!setting_info) {
|
||||
/* the setting type is unknown. That is highly unexpected
|
||||
* (and as this is currently only called from NetworkManager
|
||||
* daemon, not possible).
|
||||
*
|
||||
* Still, handle it gracefully, because later keyfile writer will become
|
||||
* public API of libnm, where @setting is (untrusted) user input.
|
||||
*
|
||||
* Gracefully here just means: ignore the setting. */
|
||||
return;
|
||||
}
|
||||
if (!property_info->param_spec)
|
||||
return;
|
||||
if (nm_streq (key, NM_SETTING_NAME))
|
||||
return;
|
||||
} else {
|
||||
if (pip->has_writer_full) {
|
||||
pip->writer_full (info, setting_info, property_info, pip, setting);
|
||||
return;
|
||||
}
|
||||
if (pip->writer_skip)
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !pip
|
||||
&& nm_streq (key, NM_SETTING_NAME))
|
||||
return;
|
||||
|
||||
if (pip && pip->writer_skip)
|
||||
return;
|
||||
nm_assert (property_info->param_spec);
|
||||
|
||||
/* Don't write secrets that are owned by user secret agents or aren't
|
||||
* supposed to be saved. VPN secrets are handled specially though since
|
||||
|
|
@ -3348,11 +3535,12 @@ write_setting_value (KeyfileWriterInfo *info,
|
|||
|
||||
if ( (!pip || !pip->writer_persist_default)
|
||||
&& g_param_value_defaults (property_info->param_spec, &value)) {
|
||||
nm_assert (!g_key_file_has_key (info->keyfile, setting_name, key, NULL));
|
||||
nm_assert (!g_key_file_has_key (info->keyfile, setting_info->setting_name, key, NULL));
|
||||
goto out_unset_value;
|
||||
}
|
||||
|
||||
if (pip && pip->writer) {
|
||||
if ( pip
|
||||
&& pip->writer) {
|
||||
pip->writer (info, setting, key, &value);
|
||||
goto out_unset_value;
|
||||
}
|
||||
|
|
@ -3363,27 +3551,27 @@ write_setting_value (KeyfileWriterInfo *info,
|
|||
|
||||
str = g_value_get_string (&value);
|
||||
if (str)
|
||||
nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str);
|
||||
nm_keyfile_plugin_kf_set_string (info->keyfile, setting_info->setting_name, key, str);
|
||||
} else if (type == G_TYPE_UINT) {
|
||||
nm_sprintf_buf (numstr, "%u", g_value_get_uint (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (type == G_TYPE_INT) {
|
||||
nm_sprintf_buf (numstr, "%d", g_value_get_int (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (type == G_TYPE_UINT64) {
|
||||
nm_sprintf_buf (numstr, "%" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (type == G_TYPE_INT64) {
|
||||
nm_sprintf_buf (numstr, "%" G_GINT64_FORMAT, g_value_get_int64 (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (type == G_TYPE_BOOLEAN) {
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key,
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key,
|
||||
g_value_get_boolean (&value)
|
||||
? "true"
|
||||
: "false");
|
||||
} else if (type == G_TYPE_CHAR) {
|
||||
nm_sprintf_buf (numstr, "%d", (int) g_value_get_schar (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (type == G_TYPE_BYTES) {
|
||||
GBytes *bytes;
|
||||
const guint8 *data;
|
||||
|
|
@ -3393,22 +3581,22 @@ write_setting_value (KeyfileWriterInfo *info,
|
|||
data = bytes ? g_bytes_get_data (bytes, &len) : NULL;
|
||||
|
||||
if (data != NULL && len > 0)
|
||||
nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_name, key, data, len);
|
||||
nm_keyfile_plugin_kf_set_integer_list_uint8 (info->keyfile, setting_info->setting_name, key, data, len);
|
||||
} else if (type == G_TYPE_STRV) {
|
||||
char **array;
|
||||
|
||||
array = (char **) g_value_get_boxed (&value);
|
||||
nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const char **const) array, g_strv_length (array));
|
||||
nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_info->setting_name, key, (const char **const) array, g_strv_length (array));
|
||||
} else if (type == G_TYPE_HASH_TABLE) {
|
||||
write_hash_of_string (info->keyfile, setting, key, &value);
|
||||
} else if (type == G_TYPE_ARRAY) {
|
||||
write_array_of_uint (info->keyfile, setting, key, &value);
|
||||
} else if (G_VALUE_HOLDS_FLAGS (&value)) {
|
||||
nm_sprintf_buf (numstr, "%u", g_value_get_flags (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else if (G_VALUE_HOLDS_ENUM (&value)) {
|
||||
nm_sprintf_buf (numstr, "%d", g_value_get_enum (&value));
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
|
||||
nm_keyfile_plugin_kf_set_value (info->keyfile, setting_info->setting_name, key, numstr);
|
||||
} else
|
||||
g_return_if_reached ();
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -159,6 +159,153 @@ gboolean nm_ip_route_attribute_validate (const char *name,
|
|||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND "lock-initrwnd"
|
||||
#define NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU "lock-mtu"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct NMIPRoutingRule NMIPRoutingRule;
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
GType nm_ip_routing_rule_get_type (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
NMIPRoutingRule *nm_ip_routing_rule_new (int addr_family);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
NMIPRoutingRule *nm_ip_routing_rule_new_clone (const NMIPRoutingRule *rule);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
NMIPRoutingRule *nm_ip_routing_rule_ref (NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_unref (NMIPRoutingRule *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_ip_routing_rule_is_sealed (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_seal (NMIPRoutingRule *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
int nm_ip_routing_rule_get_addr_family (const NMIPRoutingRule *self);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_ip_routing_rule_get_invert (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_invert (NMIPRoutingRule *self, gboolean invert);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gint64 nm_ip_routing_rule_get_priority (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_priority (NMIPRoutingRule *self, gint64 priority);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint8 nm_ip_routing_rule_get_tos (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_tos (NMIPRoutingRule *self, guint8 tos);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint8 nm_ip_routing_rule_get_ipproto (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_ipproto (NMIPRoutingRule *self, guint8 ipproto);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint16 nm_ip_routing_rule_get_source_port_start (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint16 nm_ip_routing_rule_get_source_port_end (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_source_port (NMIPRoutingRule *self, guint16 start, guint16 end);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint16 nm_ip_routing_rule_get_destination_port_start (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint16 nm_ip_routing_rule_get_destination_port_end (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_destination_port (NMIPRoutingRule *self, guint16 start, guint16 end);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint32 nm_ip_routing_rule_get_fwmark (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint32 nm_ip_routing_rule_get_fwmask (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_fwmark (NMIPRoutingRule *self, guint32 fwmark, guint32 fwmask);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint8 nm_ip_routing_rule_get_from_len (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
const char *nm_ip_routing_rule_get_from (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_from (NMIPRoutingRule *self,
|
||||
const char *from,
|
||||
guint8 len);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint8 nm_ip_routing_rule_get_to_len (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
const char *nm_ip_routing_rule_get_to (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_to (NMIPRoutingRule *self,
|
||||
const char *to,
|
||||
guint8 len);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
const char *nm_ip_routing_rule_get_iifname (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_iifname (NMIPRoutingRule *self, const char *iifname);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
const char *nm_ip_routing_rule_get_oifname (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_oifname (NMIPRoutingRule *self, const char *oifname);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint8 nm_ip_routing_rule_get_action (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_action (NMIPRoutingRule *self, guint8 action);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
guint32 nm_ip_routing_rule_get_table (const NMIPRoutingRule *self);
|
||||
NM_AVAILABLE_IN_1_18
|
||||
void nm_ip_routing_rule_set_table (NMIPRoutingRule *self, guint32 table);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
int nm_ip_routing_rule_cmp (const NMIPRoutingRule *rule,
|
||||
const NMIPRoutingRule *other);
|
||||
|
||||
NM_AVAILABLE_IN_1_18
|
||||
gboolean nm_ip_routing_rule_validate (const NMIPRoutingRule *self,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* NMIPRoutingRuleAsStringFlags:
|
||||
* @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE: no flags selected.
|
||||
* @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET: whether to allow parsing
|
||||
* IPv4 addresses.
|
||||
* @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6: whether to allow parsing
|
||||
* IPv6 addresses. If both @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET and
|
||||
* @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 are unset, it's the same
|
||||
* as setting them both.
|
||||
* @NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE: if set, ensure that the
|
||||
* rule verfies or fail.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
typedef enum { /*< flags >*/
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE = 0,
|
||||
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET = 0x1,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6 = 0x2,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE = 0x4,
|
||||
} NMIPRoutingRuleAsStringFlags;
|
||||
|
||||
NMIPRoutingRule *nm_ip_routing_rule_from_string (const char *str,
|
||||
NMIPRoutingRuleAsStringFlags to_string_flags,
|
||||
GHashTable *extra_args,
|
||||
GError **error);
|
||||
|
||||
char *nm_ip_routing_rule_to_string (const NMIPRoutingRule *self,
|
||||
NMIPRoutingRuleAsStringFlags to_string_flags,
|
||||
GHashTable *extra_args,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_TYPE_SETTING_IP_CONFIG (nm_setting_ip_config_get_type ())
|
||||
#define NM_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfig))
|
||||
#define NM_SETTING_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IPCONFIG, NMSettingIPConfigClass))
|
||||
|
|
@ -187,6 +334,9 @@ gboolean nm_ip_route_attribute_validate (const char *name,
|
|||
#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"
|
||||
|
|
@ -289,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -4541,6 +4541,29 @@ _nm_utils_generate_mac_address_mask_parse (const char *value,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name)
|
||||
{
|
||||
gs_free gpointer bin_to_free = NULL;
|
||||
gconstpointer bin;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (utf8safe_name, FALSE);
|
||||
|
||||
bin = nm_utils_buf_utf8safe_unescape (utf8safe_name, &len, &bin_to_free);
|
||||
|
||||
if (bin_to_free) {
|
||||
/* some unescaping happened... */
|
||||
|
||||
if (len != strlen (bin)) {
|
||||
/* there are embedded NUL chars. Invalid. */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return nm_utils_is_valid_iface_name (bin, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_is_valid_iface_name:
|
||||
* @name: Name of interface
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "nm-default.h"
|
||||
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "nm-utils.h"
|
||||
#include "nm-utils-private.h"
|
||||
|
|
@ -2361,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:
|
||||
|
|
@ -2548,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 ();
|
||||
}
|
||||
|
|
@ -2675,6 +2768,203 @@ test_roundtrip_conversion (gconstpointer test_data)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMIPRoutingRule *
|
||||
_rr_from_str_get_impl (const char *str, const char *const*aliases)
|
||||
{
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr = NULL;
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean vbool;
|
||||
int addr_family;
|
||||
int i;
|
||||
NMIPRoutingRuleAsStringFlags to_string_flags;
|
||||
|
||||
rr = nm_ip_routing_rule_from_string (str,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE,
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (rr, error);
|
||||
|
||||
addr_family = nm_ip_routing_rule_get_addr_family (rr);
|
||||
g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
if (addr_family == AF_INET)
|
||||
to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET;
|
||||
else
|
||||
to_string_flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6;
|
||||
|
||||
for (i = 0; TRUE; i++) {
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr2 = NULL;
|
||||
gs_free char *str1 = NULL;
|
||||
gs_unref_variant GVariant *variant1 = NULL;
|
||||
const char *cstr1;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
rr2 = nm_ip_routing_rule_ref (rr);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rr2 = nm_ip_routing_rule_from_string (str,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| (nmtst_get_rand_bool () ? to_string_flags : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE),
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (rr, error);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
str1 = nm_ip_routing_rule_to_string (rr,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| (nmtst_get_rand_bool () ? to_string_flags : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE),
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (str1 && str1[0], error);
|
||||
|
||||
g_assert_cmpstr (str, ==, str1);
|
||||
|
||||
rr2 = nm_ip_routing_rule_from_string (str1,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| (nmtst_get_rand_bool () ? to_string_flags : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE),
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (rr, error);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
variant1 = nm_ip_routing_rule_to_dbus (rr);
|
||||
g_assert (variant1);
|
||||
g_assert (g_variant_is_floating (variant1));
|
||||
g_assert (g_variant_is_of_type (variant1, G_VARIANT_TYPE_VARDICT));
|
||||
|
||||
rr2 = nm_ip_routing_rule_from_dbus (variant1,
|
||||
TRUE,
|
||||
&error);
|
||||
nmtst_assert_success (rr, error);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!aliases || !aliases[0])
|
||||
goto done;
|
||||
cstr1 = (aliases++)[0];
|
||||
rr2 = nm_ip_routing_rule_from_string (cstr1,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| (nmtst_get_rand_bool () ? to_string_flags : NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE),
|
||||
NULL,
|
||||
&error);
|
||||
nmtst_assert_success (rr, error);
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert (rr2);
|
||||
vbool = nm_ip_routing_rule_validate (rr, &error);
|
||||
nmtst_assert_success (vbool, error);
|
||||
vbool = nm_ip_routing_rule_validate (rr2, &error);
|
||||
nmtst_assert_success (vbool, error);
|
||||
|
||||
g_assert_cmpint (nm_ip_routing_rule_cmp (rr, rr2), ==, 0);
|
||||
g_assert_cmpint (nm_ip_routing_rule_cmp (rr2, rr), ==, 0);
|
||||
}
|
||||
|
||||
done:
|
||||
return g_steal_pointer (&rr);
|
||||
}
|
||||
#define _rr_from_str_get(a, ...) _rr_from_str_get_impl (a, &(NM_MAKE_STRV (NULL, ##__VA_ARGS__))[1])
|
||||
|
||||
#define _rr_from_str(...) \
|
||||
G_STMT_START { \
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *_rr = NULL; \
|
||||
\
|
||||
_rr = _rr_from_str_get (__VA_ARGS__); \
|
||||
g_assert (_rr); \
|
||||
} G_STMT_END
|
||||
|
||||
static void
|
||||
test_routing_rule (gconstpointer test_data)
|
||||
{
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rr1 = NULL;
|
||||
gboolean success;
|
||||
char ifname_buf[16];
|
||||
|
||||
_rr_from_str ("priority 5 from 0.0.0.0 table 1",
|
||||
" from 0.0.0\\.0 \\priority 5 lookup 1 ");
|
||||
_rr_from_str ("priority 5 from 0.0.0.0/0 table 4");
|
||||
_rr_from_str ("priority 5 to 0.0.0.0 table 6");
|
||||
_rr_from_str ("priority 5 to 0.0.0.0 table 254",
|
||||
"priority 5 to 0.0.0.0/32");
|
||||
_rr_from_str ("priority 5 from 1.2.3.4 table 15",
|
||||
"priority 5 from 1.2.3.4/32 table 0xF ",
|
||||
"priority 5 from 1.2.3.4/32 to 0.0.0.0/0 lookup 15 ");
|
||||
_rr_from_str ("priority 5 from 1.2.3.4 to 0.0.0.0 table 8");
|
||||
_rr_from_str ("priority 5 to a:b:c:: tos 0x16 table 25",
|
||||
"priority 5 to a:b:c::/128 table 0x19 tos 16",
|
||||
"priority 5 to a:b:c::/128 lookup 0x19 dsfield 16",
|
||||
"priority 5 to a:b:c::/128 lookup 0x19 dsfield 16 fwmark 0/0x00",
|
||||
"priority 5 to a:b:c:: from all lookup 0x19 dsfield 16 fwmark 0x0/0");
|
||||
_rr_from_str ("priority 5 from :: fwmark 0 table 25",
|
||||
"priority 5 from ::/128 to all table 0x19 fwmark 0/0xFFFFFFFF",
|
||||
"priority 5 from :: to ::/0 table 0x19 fwmark 0x00/4294967295");
|
||||
_rr_from_str ("priority 5 from :: iif aab table 25");
|
||||
_rr_from_str ("priority 5 from :: iif aab oif er table 25",
|
||||
"priority 5 from :: table 0x19 dev \\a\\a\\b oif er");
|
||||
_rr_from_str ("priority 5 from :: iif a\\\\303b table 25");
|
||||
_rr_from_str ("priority 5 to 0.0.0.0 sport 10 table 6",
|
||||
"priority 5 to 0.0.0.0 sport 10-10 table 6");
|
||||
_rr_from_str ("not priority 5 to 0.0.0.0 dport 10-133 table 6",
|
||||
"priority 5 to 0.0.0.0 not dport 10-133 not table 6",
|
||||
"priority 5 to 0.0.0.0 not dport 10-\\ 133 not table 6");
|
||||
_rr_from_str ("priority 5 to 0.0.0.0 ipproto 10 sport 10 table 6");
|
||||
|
||||
rr1 = _rr_from_str_get ("priority 5 from :: iif aab table 25");
|
||||
g_assert_cmpstr (nm_ip_routing_rule_get_iifname (rr1), ==, "aab");
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, FALSE, ifname_buf);
|
||||
g_assert (!success);
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, TRUE, ifname_buf);
|
||||
g_assert_cmpstr (ifname_buf, ==, "aab");
|
||||
g_assert (success);
|
||||
|
||||
rr1 = _rr_from_str_get ("priority 5 from :: iif a\\\\303\\\\261xb table 254");
|
||||
g_assert_cmpstr (nm_ip_routing_rule_get_iifname (rr1), ==, "a\\303\\261xb");
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, FALSE, ifname_buf);
|
||||
g_assert (!success);
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, TRUE, ifname_buf);
|
||||
g_assert_cmpstr (ifname_buf, ==, "a\303\261xb");
|
||||
g_assert (success);
|
||||
nm_clear_pointer (&rr1, nm_ip_routing_rule_unref);
|
||||
|
||||
rr1 = _rr_from_str_get ("priority 5 from :: oif \\\\101=\\\\303\\\\261xb table 7");
|
||||
g_assert_cmpstr (nm_ip_routing_rule_get_oifname (rr1), ==, "\\101=\\303\\261xb");
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, FALSE, ifname_buf);
|
||||
g_assert_cmpstr (ifname_buf, ==, "A=\303\261xb");
|
||||
g_assert (success);
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, TRUE, ifname_buf);
|
||||
g_assert (!success);
|
||||
nm_clear_pointer (&rr1, nm_ip_routing_rule_unref);
|
||||
|
||||
rr1 = _rr_from_str_get ("priority 5 to 0.0.0.0 tos 0x10 table 7");
|
||||
g_assert_cmpstr (NULL, ==, nm_ip_routing_rule_get_from (rr1));
|
||||
g_assert (!nm_ip_routing_rule_get_from_bin (rr1));
|
||||
g_assert_cmpint (0, ==, nm_ip_routing_rule_get_from_len (rr1));
|
||||
g_assert_cmpstr ("0.0.0.0", ==, nm_ip_routing_rule_get_to (rr1));
|
||||
g_assert (nm_ip_addr_is_null (AF_INET, nm_ip_routing_rule_get_to_bin (rr1)));
|
||||
g_assert_cmpint (32, ==, nm_ip_routing_rule_get_to_len (rr1));
|
||||
g_assert_cmpint (7, ==, nm_ip_routing_rule_get_table (rr1));
|
||||
g_assert_cmpint (0x10, ==, nm_ip_routing_rule_get_tos (rr1));
|
||||
nm_clear_pointer (&rr1, nm_ip_routing_rule_unref);
|
||||
|
||||
rr1 = _rr_from_str_get ("priority 5 from :: iif a\\\\303\\\\261\\,x\\;b table 254",
|
||||
"priority 5 from :: iif a\\\\303\\\\261,x;b table 254");
|
||||
g_assert_cmpstr (nm_ip_routing_rule_get_iifname (rr1), ==, "a\\303\\261,x;b");
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, FALSE, ifname_buf);
|
||||
g_assert (!success);
|
||||
success = nm_ip_routing_rule_get_xifname_bin (rr1, TRUE, ifname_buf);
|
||||
g_assert_cmpstr (ifname_buf, ==, "a\303\261,x;b");
|
||||
g_assert (success);
|
||||
nm_clear_pointer (&rr1, nm_ip_routing_rule_unref);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int
|
||||
|
|
@ -2753,9 +3043,12 @@ 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);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1536,13 +1536,57 @@ global:
|
|||
nm_bridge_vlan_set_untagged;
|
||||
nm_bridge_vlan_to_str;
|
||||
nm_bridge_vlan_unref;
|
||||
nm_ip_routing_rule_as_string_flags_get_type;
|
||||
nm_ip_routing_rule_cmp;
|
||||
nm_ip_routing_rule_from_string;
|
||||
nm_ip_routing_rule_get_action;
|
||||
nm_ip_routing_rule_get_addr_family;
|
||||
nm_ip_routing_rule_get_destination_port_end;
|
||||
nm_ip_routing_rule_get_destination_port_start;
|
||||
nm_ip_routing_rule_get_from;
|
||||
nm_ip_routing_rule_get_from_len;
|
||||
nm_ip_routing_rule_get_fwmark;
|
||||
nm_ip_routing_rule_get_fwmask;
|
||||
nm_ip_routing_rule_get_iifname;
|
||||
nm_ip_routing_rule_get_invert;
|
||||
nm_ip_routing_rule_get_ipproto;
|
||||
nm_ip_routing_rule_get_oifname;
|
||||
nm_ip_routing_rule_get_priority;
|
||||
nm_ip_routing_rule_get_source_port_end;
|
||||
nm_ip_routing_rule_get_source_port_start;
|
||||
nm_ip_routing_rule_get_table;
|
||||
nm_ip_routing_rule_get_to;
|
||||
nm_ip_routing_rule_get_to_len;
|
||||
nm_ip_routing_rule_get_tos;
|
||||
nm_ip_routing_rule_get_type;
|
||||
nm_ip_routing_rule_is_sealed;
|
||||
nm_ip_routing_rule_new;
|
||||
nm_ip_routing_rule_new_clone;
|
||||
nm_ip_routing_rule_ref;
|
||||
nm_ip_routing_rule_seal;
|
||||
nm_ip_routing_rule_set_action;
|
||||
nm_ip_routing_rule_set_destination_port;
|
||||
nm_ip_routing_rule_set_from;
|
||||
nm_ip_routing_rule_set_fwmark;
|
||||
nm_ip_routing_rule_set_iifname;
|
||||
nm_ip_routing_rule_set_invert;
|
||||
nm_ip_routing_rule_set_ipproto;
|
||||
nm_ip_routing_rule_set_oifname;
|
||||
nm_ip_routing_rule_set_priority;
|
||||
nm_ip_routing_rule_set_source_port;
|
||||
nm_ip_routing_rule_set_table;
|
||||
nm_ip_routing_rule_set_to;
|
||||
nm_ip_routing_rule_set_tos;
|
||||
nm_ip_routing_rule_to_string;
|
||||
nm_ip_routing_rule_unref;
|
||||
nm_ip_routing_rule_validate;
|
||||
nm_lldp_neighbor_get_attr_value;
|
||||
nm_setting_bridge_add_vlan;
|
||||
nm_setting_bridge_clear_vlans;
|
||||
nm_setting_bridge_get_num_vlans;
|
||||
nm_setting_bridge_get_vlan;
|
||||
nm_setting_bridge_get_vlan_filtering;
|
||||
nm_setting_bridge_get_vlan_default_pvid;
|
||||
nm_setting_bridge_get_vlan_filtering;
|
||||
nm_setting_bridge_port_add_vlan;
|
||||
nm_setting_bridge_port_clear_vlans;
|
||||
nm_setting_bridge_port_get_num_vlans;
|
||||
|
|
@ -1551,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;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ NM_AUTO_DEFINE_FCN0 (NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref)
|
|||
#define nm_auto_unref_ip_route nm_auto (_nm_auto_unref_ip_route)
|
||||
NM_AUTO_DEFINE_FCN0 (NMIPRoute *, _nm_auto_unref_ip_route, nm_ip_route_unref)
|
||||
|
||||
#define nm_auto_unref_ip_routing_rule nm_auto(_nm_auto_unref_ip_routing_rule)
|
||||
NM_AUTO_DEFINE_FCN0 (NMIPRoutingRule *, _nm_auto_unref_ip_routing_rule, nm_ip_routing_rule_unref)
|
||||
|
||||
#define nm_auto_unref_sriov_vf nm_auto (_nm_auto_unref_sriov_vf)
|
||||
NM_AUTO_DEFINE_FCN0 (NMSriovVF *, _nm_auto_unref_sriov_vf, nm_sriov_vf_unref)
|
||||
|
||||
|
|
|
|||
|
|
@ -2505,6 +2505,59 @@ _nm_utils_unescape_plain (char *str, const char *candidates, gboolean do_strip)
|
|||
return str;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_utils_str_simpletokens_extract_next (char **p_line_start)
|
||||
{
|
||||
char *s_next;
|
||||
char *s_start;
|
||||
gsize j;
|
||||
|
||||
s_start = *p_line_start;
|
||||
if (!s_start)
|
||||
return NULL;
|
||||
|
||||
s_start = nm_str_skip_leading_spaces (s_start);
|
||||
|
||||
if (s_start[0] == '\0') {
|
||||
*p_line_start = s_start;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_next = s_start;
|
||||
j = 0;
|
||||
while (TRUE) {
|
||||
if (s_next[0] == '\0') {
|
||||
s_start[j] = '\0';
|
||||
*p_line_start = s_next;
|
||||
return s_start;
|
||||
}
|
||||
if (s_next[0] == '\\') {
|
||||
s_next++;
|
||||
if (s_next[0] == '\0') {
|
||||
/* trailing backslash at end of word. That's an error,
|
||||
* but we silently drop the backslash and signal success. */
|
||||
*p_line_start = s_next;
|
||||
if (j == 0)
|
||||
return NULL;
|
||||
s_start[j] = '\0';
|
||||
return s_start;
|
||||
}
|
||||
|
||||
s_start[j++] = (s_next++)[0];
|
||||
continue;
|
||||
}
|
||||
if (!g_ascii_isspace (s_next[0])) {
|
||||
s_start[j++] = (s_next++)[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
nm_assert (j > 0);
|
||||
s_start[j] = '\0';
|
||||
*p_line_start = nm_str_skip_leading_spaces (&s_next[1]);
|
||||
return s_start;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,16 @@ typedef struct {
|
|||
|
||||
extern const NMIPAddr nm_ip_addr_zero;
|
||||
|
||||
static inline gboolean
|
||||
nm_ip_addr_is_null (int addr_family, gconstpointer addr)
|
||||
{
|
||||
nm_assert (addr);
|
||||
if (addr_family == AF_INET6)
|
||||
return IN6_IS_ADDR_UNSPECIFIED ((const struct in6_addr *) addr);
|
||||
nm_assert (addr_family == AF_INET);
|
||||
return ((const struct in_addr *) addr)->s_addr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_ip_addr_set (int addr_family, gpointer dst, gconstpointer src)
|
||||
{
|
||||
|
|
@ -436,6 +446,8 @@ int nm_utils_dbus_path_cmp (const char *dbus_path_a, const char *dbus_path_b);
|
|||
|
||||
const char **nm_utils_strsplit_set (const char *str, const char *delimiters, gboolean allow_escaping);
|
||||
|
||||
char *nm_utils_str_simpletokens_extract_next (char **p_line_start);
|
||||
|
||||
gssize nm_utils_strv_find_first (char **list, gssize len, const char *needle);
|
||||
|
||||
char **_nm_utils_strv_cleanup (char **strv,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include <linux/fib_rules.h>
|
||||
|
||||
#include "nm-utils/nm-c-list.h"
|
||||
|
||||
#include "nm-common-macros.h"
|
||||
|
|
@ -908,6 +910,48 @@ nm_match_spec_device_by_pllink (const NMPlatformLink *pllink,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMPlatformRoutingRule *
|
||||
nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule,
|
||||
NMPlatformRoutingRule *out_pl)
|
||||
{
|
||||
nm_assert (rule);
|
||||
nm_assert (nm_ip_routing_rule_validate (rule, NULL));
|
||||
nm_assert (out_pl);
|
||||
|
||||
*out_pl = (NMPlatformRoutingRule) {
|
||||
.addr_family = nm_ip_routing_rule_get_addr_family (rule),
|
||||
.flags = ( nm_ip_routing_rule_get_invert (rule)
|
||||
? FIB_RULE_INVERT
|
||||
: 0),
|
||||
.priority = nm_ip_routing_rule_get_priority (rule),
|
||||
.tos = nm_ip_routing_rule_get_tos (rule),
|
||||
.ip_proto = nm_ip_routing_rule_get_ipproto (rule),
|
||||
.fwmark = nm_ip_routing_rule_get_fwmark (rule),
|
||||
.fwmask = nm_ip_routing_rule_get_fwmask (rule),
|
||||
.sport_range = {
|
||||
.start = nm_ip_routing_rule_get_source_port_start (rule),
|
||||
.end = nm_ip_routing_rule_get_source_port_end (rule),
|
||||
},
|
||||
.dport_range = {
|
||||
.start = nm_ip_routing_rule_get_destination_port_start (rule),
|
||||
.end = nm_ip_routing_rule_get_destination_port_end (rule),
|
||||
},
|
||||
.src = *(nm_ip_routing_rule_get_from_bin (rule) ?: &nm_ip_addr_zero),
|
||||
.dst = *(nm_ip_routing_rule_get_to_bin (rule) ?: &nm_ip_addr_zero),
|
||||
.src_len = nm_ip_routing_rule_get_from_len (rule),
|
||||
.dst_len = nm_ip_routing_rule_get_to_len (rule),
|
||||
.action = nm_ip_routing_rule_get_action (rule),
|
||||
.table = nm_ip_routing_rule_get_table (rule),
|
||||
};
|
||||
|
||||
nm_ip_routing_rule_get_xifname_bin (rule, TRUE, out_pl->iifname);
|
||||
nm_ip_routing_rule_get_xifname_bin (rule, FALSE, out_pl->oifname);
|
||||
|
||||
return out_pl;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMShutdownWaitObjHandle {
|
||||
CList lst;
|
||||
GObject *watched_obj;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@
|
|||
|
||||
#include "nm-core-utils.h"
|
||||
|
||||
#include "nm-setting-ip-config.h"
|
||||
#include "platform/nm-platform.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *nm_utils_get_ip_config_method (NMConnection *connection,
|
||||
|
|
@ -60,6 +63,11 @@ int nm_match_spec_device_by_pllink (const NMPlatformLink *pllink,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule,
|
||||
NMPlatformRoutingRule *out_pl);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* during shutdown, there are two relevant timeouts. One is
|
||||
* NM_SHUTDOWN_TIMEOUT_MS which is plenty of time, that we give for all
|
||||
* actions to complete. Of course, during shutdown components should hurry
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "nm-manager.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-object.h"
|
||||
#include "platform/nmp-rules-manager.h"
|
||||
#include "ndisc/nm-ndisc.h"
|
||||
#include "ndisc/nm-lndp-ndisc.h"
|
||||
#include "dhcp/nm-dhcp-manager.h"
|
||||
|
|
@ -6408,6 +6409,84 @@ lldp_init (NMDevice *self, gboolean restart)
|
|||
}
|
||||
}
|
||||
|
||||
/* set-mode can be:
|
||||
* - TRUE: sync with new rules.
|
||||
* - FALSE: sync, but remove all rules (== flush)
|
||||
* - DEFAULT: forget about all the rules that we previously tracked,
|
||||
* but don't actually remove them. This is when quitting NM
|
||||
* we want to keep the rules.
|
||||
* The problem is, after restart of NM, the rule manager will
|
||||
* no longer remember that NM added these rules and treat them
|
||||
* as externally added ones. Don't restart NetworkManager if
|
||||
* you care about that.
|
||||
*/
|
||||
static void
|
||||
_routing_rules_sync (NMDevice *self,
|
||||
NMTernary set_mode)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMPRulesManager *rules_manager = nm_netns_get_rules_manager (nm_device_get_netns (self));
|
||||
gboolean untrack_only_dirty = FALSE;
|
||||
gboolean keep_deleted_rules;
|
||||
gpointer user_tag;
|
||||
|
||||
user_tag = priv;
|
||||
|
||||
if (set_mode == NM_TERNARY_TRUE) {
|
||||
NMConnection *applied_connection;
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint i, num;
|
||||
int is_ipv4;
|
||||
|
||||
untrack_only_dirty = TRUE;
|
||||
nmp_rules_manager_set_dirty (rules_manager, user_tag);
|
||||
|
||||
applied_connection = nm_device_get_applied_connection (self);
|
||||
|
||||
for (is_ipv4 = 0; applied_connection && is_ipv4 < 2; is_ipv4++) {
|
||||
int addr_family = is_ipv4 ? AF_INET : AF_INET6;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip_config (applied_connection, addr_family);
|
||||
if (!s_ip)
|
||||
continue;
|
||||
|
||||
num = nm_setting_ip_config_get_num_routing_rules (s_ip);
|
||||
for (i = 0; i < num; i++) {
|
||||
NMPlatformRoutingRule plrule;
|
||||
NMIPRoutingRule *rule;
|
||||
|
||||
rule = nm_setting_ip_config_get_routing_rule (s_ip, i);
|
||||
nm_ip_routing_rule_to_platform (rule, &plrule);
|
||||
nmp_rules_manager_track (rules_manager,
|
||||
&plrule,
|
||||
10,
|
||||
user_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_untrack_all (rules_manager, user_tag, !untrack_only_dirty);
|
||||
|
||||
keep_deleted_rules = FALSE;
|
||||
if (set_mode == NM_TERNARY_DEFAULT) {
|
||||
/* when exiting NM, we leave the device up and the rules configured.
|
||||
* We just all nmp_rules_manager_sync() to forget about the synced rules,
|
||||
* but we don't actually delete them.
|
||||
*
|
||||
* FIXME: that is a problem after restart of NetworkManager, because these
|
||||
* rules will look like externally added, and NM will no longer remove
|
||||
* them.
|
||||
* To fix that, we could during "assume" mark the rules of the profile
|
||||
* as owned (and "added" by the device). The problem with that is that it
|
||||
* wouldn't cover rules that devices add by internal decision (not because
|
||||
* of a setting in the profile, e.g. WireGuard could setup policy routing).
|
||||
* Maybe it would be better to remember these orphaned rules at exit in a
|
||||
* file and track them after restart again. */
|
||||
keep_deleted_rules = TRUE;
|
||||
}
|
||||
nmp_rules_manager_sync (rules_manager, keep_deleted_rules);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tc_commit (NMDevice *self)
|
||||
{
|
||||
|
|
@ -6519,6 +6598,8 @@ activate_stage2_device_config (NMDevice *self)
|
|||
}
|
||||
}
|
||||
|
||||
_routing_rules_sync (self, NM_TERNARY_TRUE);
|
||||
|
||||
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
||||
if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
|
||||
if (no_firmware)
|
||||
|
|
@ -14350,6 +14431,11 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
|||
}
|
||||
}
|
||||
|
||||
_routing_rules_sync (self,
|
||||
cleanup_type == CLEANUP_TYPE_KEEP
|
||||
? NM_TERNARY_DEFAULT
|
||||
: NM_TERNARY_FALSE);
|
||||
|
||||
if (ifindex > 0)
|
||||
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), ifindex, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -4144,7 +4144,7 @@ _nl_msg_new_routing_rule (int nlmsg_type,
|
|||
.src_len = routing_rule->src_len,
|
||||
.dst_len = routing_rule->dst_len,
|
||||
.tos = routing_rule->tos,
|
||||
.table = table,
|
||||
.table = table < 0x100u ? (guint8) table : (guint8) RT_TABLE_UNSPEC,
|
||||
.action = routing_rule->action,
|
||||
|
||||
/* we only allow setting the "not" flag. */
|
||||
|
|
|
|||
|
|
@ -471,7 +471,8 @@ nmp_rules_manager_untrack_all (NMPRulesManager *self,
|
|||
}
|
||||
|
||||
void
|
||||
nmp_rules_manager_sync (NMPRulesManager *self)
|
||||
nmp_rules_manager_sync (NMPRulesManager *self,
|
||||
gboolean keep_deleted_rules)
|
||||
{
|
||||
const NMDedupMultiHeadEntry *pl_head_entry;
|
||||
NMDedupMultiIter pl_iter;
|
||||
|
|
@ -486,7 +487,7 @@ nmp_rules_manager_sync (NMPRulesManager *self)
|
|||
if (!self->by_data)
|
||||
return;
|
||||
|
||||
_LOGD ("sync");
|
||||
_LOGD ("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
|
||||
|
||||
pl_head_entry = nm_platform_lookup_obj_type (self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
|
||||
if (pl_head_entry) {
|
||||
|
|
@ -508,6 +509,11 @@ nmp_rules_manager_sync (NMPRulesManager *self)
|
|||
obj_data->added_by_us = FALSE;
|
||||
}
|
||||
|
||||
if (keep_deleted_rules) {
|
||||
_LOGD ("forget/leak rule added by us: %s", nmp_object_to_string (plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rules_to_delete)
|
||||
rules_to_delete = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||
|
||||
|
|
@ -558,6 +564,7 @@ nmp_rules_manager_track_default (NMPRulesManager *self,
|
|||
.priority = 0,
|
||||
.table = RT_TABLE_LOCAL,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.protocol = RTPROT_KERNEL,
|
||||
}),
|
||||
priority,
|
||||
user_tag);
|
||||
|
|
@ -567,6 +574,7 @@ nmp_rules_manager_track_default (NMPRulesManager *self,
|
|||
.priority = 32766,
|
||||
.table = RT_TABLE_MAIN,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.protocol = RTPROT_KERNEL,
|
||||
}),
|
||||
priority,
|
||||
user_tag);
|
||||
|
|
@ -576,6 +584,7 @@ nmp_rules_manager_track_default (NMPRulesManager *self,
|
|||
.priority = 32767,
|
||||
.table = RT_TABLE_DEFAULT,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.protocol = RTPROT_KERNEL,
|
||||
}),
|
||||
priority,
|
||||
user_tag);
|
||||
|
|
@ -587,6 +596,7 @@ nmp_rules_manager_track_default (NMPRulesManager *self,
|
|||
.priority = 0,
|
||||
.table = RT_TABLE_LOCAL,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.protocol = RTPROT_KERNEL,
|
||||
}),
|
||||
priority,
|
||||
user_tag);
|
||||
|
|
@ -596,6 +606,7 @@ nmp_rules_manager_track_default (NMPRulesManager *self,
|
|||
.priority = 32766,
|
||||
.table = RT_TABLE_MAIN,
|
||||
.action = FR_ACT_TO_TBL,
|
||||
.protocol = RTPROT_KERNEL,
|
||||
}),
|
||||
priority,
|
||||
user_tag);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ void nmp_rules_manager_untrack_all (NMPRulesManager *self,
|
|||
gconstpointer user_tag,
|
||||
gboolean all /* or only dirty */);
|
||||
|
||||
void nmp_rules_manager_sync (NMPRulesManager *self);
|
||||
void nmp_rules_manager_sync (NMPRulesManager *self,
|
||||
gboolean keep_deleted_rules);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -1546,12 +1546,12 @@ again:
|
|||
USER_TAG_2);
|
||||
}
|
||||
if (nmtst_get_rand_int () % objs_sync->len == 0) {
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len);
|
||||
|
||||
for (i = 0; i < objs_sync->len; i++) {
|
||||
|
|
@ -1578,12 +1578,12 @@ again:
|
|||
break;
|
||||
}
|
||||
if (nmtst_get_rand_int () % objs_sync->len == 0) {
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
g_assert_cmpint (nmtstp_platform_routing_rules_get_count (platform, AF_UNSPEC), ==, objs_sync->len - i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
nmp_rules_manager_sync (rules_manager);
|
||||
nmp_rules_manager_sync (rules_manager, FALSE);
|
||||
|
||||
} else {
|
||||
for (i = 0; i < objs->len;) {
|
||||
|
|
|
|||
|
|
@ -2083,7 +2083,7 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, v, NULL);
|
||||
|
||||
g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME,
|
||||
svGetValueBoolean (ifcfg, "DHCPV6_SEND_HOSTNAME", TRUE), NULL);
|
||||
svGetValueBoolean (ifcfg, "DHCPV6_SEND_HOSTNAME", TRUE), NULL);
|
||||
|
||||
/* Read static IP addresses.
|
||||
* Read them even for AUTO and DHCP methods - in this case the addresses are
|
||||
|
|
@ -4316,6 +4316,84 @@ parse_ethtool_option (const char *value,
|
|||
}
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
read_routing_rules_parse (shvarFile *ifcfg,
|
||||
gboolean routes_read)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *arr = NULL;
|
||||
gs_free const char **keys = NULL;
|
||||
guint i, len;
|
||||
|
||||
keys = svGetKeysSorted (ifcfg, SV_KEY_TYPE_ROUTING_RULE4 | SV_KEY_TYPE_ROUTING_RULE6, &len);
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
if (!routes_read) {
|
||||
PARSE_WARNING ("'rule-' or 'rule6-' files are present; Policy routing rules (ROUTING_RULE*) settings are ignored");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
arr = g_ptr_array_new_full (len, (GDestroyNotify) nm_ip_routing_rule_unref);
|
||||
for (i = 0; i < len; i++) {
|
||||
const char *key = keys[i];
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL;
|
||||
gs_free_error GError *local = NULL;
|
||||
gs_free char *value_to_free = NULL;
|
||||
const char *value;
|
||||
gboolean key_is_ipv4;
|
||||
|
||||
key_is_ipv4 = (key[NM_STRLEN ("ROUTING_RULE")] == '_');
|
||||
nm_assert ( key_is_ipv4 == NM_STR_HAS_PREFIX (key, "ROUTING_RULE_"));
|
||||
nm_assert (!key_is_ipv4 == NM_STR_HAS_PREFIX (key, "ROUTING_RULE6_"));
|
||||
|
||||
value = svGetValueStr (ifcfg, key, &value_to_free);
|
||||
if (!value)
|
||||
continue;
|
||||
|
||||
rule = nm_ip_routing_rule_from_string (value,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| (key_is_ipv4
|
||||
? NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET
|
||||
: NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6),
|
||||
NULL,
|
||||
&local);
|
||||
if (!rule) {
|
||||
PARSE_WARNING ("invalid routing rule %s=\"%s\": %s", key, value, local->message);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_ptr_array_add (arr, g_steal_pointer (&rule));
|
||||
}
|
||||
|
||||
if (arr->len == 0)
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&arr);
|
||||
}
|
||||
|
||||
static void
|
||||
read_routing_rules (shvarFile *ifcfg,
|
||||
gboolean routes_read,
|
||||
NMSettingIPConfig *s_ip4,
|
||||
NMSettingIPConfig *s_ip6)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *routing_rules = NULL;
|
||||
guint i;
|
||||
|
||||
routing_rules = read_routing_rules_parse (ifcfg, routes_read);
|
||||
if (!routing_rules)
|
||||
return;
|
||||
|
||||
for (i = 0; i < routing_rules->len; i++) {
|
||||
NMIPRoutingRule *rule = routing_rules->pdata[i];
|
||||
|
||||
nm_setting_ip_config_add_routing_rule ( (nm_ip_routing_rule_get_addr_family (rule) == AF_INET)
|
||||
? s_ip4
|
||||
: s_ip6,
|
||||
rule);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_ethtool_options (shvarFile *ifcfg, NMConnection *connection)
|
||||
{
|
||||
|
|
@ -5817,8 +5895,7 @@ connection_from_file_full (const char *filename,
|
|||
error);
|
||||
if (!s_ip6)
|
||||
return NULL;
|
||||
else
|
||||
nm_connection_add_setting (connection, s_ip6);
|
||||
nm_connection_add_setting (connection, s_ip6);
|
||||
|
||||
s_ip4 = make_ip4_setting (main_ifcfg,
|
||||
network_ifcfg,
|
||||
|
|
@ -5827,12 +5904,15 @@ connection_from_file_full (const char *filename,
|
|||
error);
|
||||
if (!s_ip4)
|
||||
return NULL;
|
||||
else {
|
||||
read_aliases (NM_SETTING_IP_CONFIG (s_ip4),
|
||||
!has_ip4_defroute && !nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (s_ip4)),
|
||||
filename);
|
||||
nm_connection_add_setting (connection, s_ip4);
|
||||
}
|
||||
read_aliases (NM_SETTING_IP_CONFIG (s_ip4),
|
||||
!has_ip4_defroute && !nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (s_ip4)),
|
||||
filename);
|
||||
nm_connection_add_setting (connection, s_ip4);
|
||||
|
||||
read_routing_rules (main_ifcfg,
|
||||
!has_complex_routes_v4 && !has_complex_routes_v6,
|
||||
NM_SETTING_IP_CONFIG (s_ip4),
|
||||
NM_SETTING_IP_CONFIG (s_ip6));
|
||||
|
||||
s_sriov = make_sriov_setting (main_ifcfg);
|
||||
if (s_sriov)
|
||||
|
|
|
|||
|
|
@ -2954,6 +2954,52 @@ write_ip6_setting (NMConnection *connection,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
write_ip_routing_rules (NMConnection *connection,
|
||||
shvarFile *ifcfg,
|
||||
gboolean route_ignore)
|
||||
{
|
||||
gsize idx;
|
||||
int is_ipv4;
|
||||
|
||||
svUnsetAll (ifcfg, SV_KEY_TYPE_ROUTING_RULE4 | SV_KEY_TYPE_ROUTING_RULE6);
|
||||
|
||||
if (route_ignore)
|
||||
return;
|
||||
|
||||
idx = 0;
|
||||
|
||||
for (is_ipv4 = 1; is_ipv4 >= 0; is_ipv4--) {
|
||||
const int addr_family = is_ipv4 ? AF_INET : AF_INET6;
|
||||
NMSettingIPConfig *s_ip;
|
||||
guint i, num;
|
||||
|
||||
s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
|
||||
if (!s_ip)
|
||||
continue;
|
||||
|
||||
num = nm_setting_ip_config_get_num_routing_rules (s_ip);
|
||||
for (i = 0; i < num; i++) {
|
||||
NMIPRoutingRule *rule = nm_setting_ip_config_get_routing_rule (s_ip, i);
|
||||
gs_free const char *s = NULL;
|
||||
char key[64];
|
||||
|
||||
s = nm_ip_routing_rule_to_string (rule,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
if (is_ipv4)
|
||||
numbered_tag (key, "ROUTING_RULE_", ++idx);
|
||||
else
|
||||
numbered_tag (key, "ROUTING_RULE6_", ++idx);
|
||||
svSetValueStr (ifcfg, key, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
escape_id (const char *id)
|
||||
{
|
||||
|
|
@ -3176,6 +3222,15 @@ do_write_construct (NMConnection *connection,
|
|||
has_complex_routes_v4 ? "" : "6");
|
||||
return FALSE;
|
||||
}
|
||||
if ( ( s_ip4
|
||||
&& nm_setting_ip_config_get_num_routing_rules (s_ip4) > 0)
|
||||
|| ( s_ip6
|
||||
&& nm_setting_ip_config_get_num_routing_rules (s_ip6) > 0)) {
|
||||
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
|
||||
"Cannot configure routing rules on a connection that has an associated 'rule%s-' file",
|
||||
has_complex_routes_v4 ? "" : "6");
|
||||
return FALSE;
|
||||
}
|
||||
route_ignore = TRUE;
|
||||
} else
|
||||
route_ignore = FALSE;
|
||||
|
|
@ -3193,6 +3248,10 @@ do_write_construct (NMConnection *connection,
|
|||
error))
|
||||
return FALSE;
|
||||
|
||||
write_ip_routing_rules (connection,
|
||||
ifcfg,
|
||||
route_ignore);
|
||||
|
||||
write_connection_setting (s_con, ifcfg);
|
||||
|
||||
NM_SET_OUT (out_ifcfg, g_steal_pointer (&ifcfg));
|
||||
|
|
|
|||
|
|
@ -879,10 +879,25 @@ _is_all_digits (const char *str)
|
|||
|
||||
#define IS_NUMBERED_TAG(key, tab_name) \
|
||||
({ \
|
||||
const char *_key = (key); \
|
||||
const char *_key2 = (key); \
|
||||
\
|
||||
( (strncmp (_key, tab_name, NM_STRLEN (tab_name)) == 0) \
|
||||
&& _is_all_digits (&_key[NM_STRLEN (tab_name)])); \
|
||||
( (strncmp (_key2, tab_name, NM_STRLEN (tab_name)) == 0) \
|
||||
&& _is_all_digits (&_key2[NM_STRLEN (tab_name)])); \
|
||||
})
|
||||
|
||||
#define IS_NUMBERED_TAG_PARSE(key, tab_name, out_idx) \
|
||||
({ \
|
||||
const char *_key = (key); \
|
||||
gint64 _idx; \
|
||||
gboolean _good = FALSE; \
|
||||
gint64 *_out_idx = (out_idx); \
|
||||
\
|
||||
if ( IS_NUMBERED_TAG (_key, ""tab_name"") \
|
||||
&& (_idx = _nm_utils_ascii_str_to_int64 (&_key[NM_STRLEN (tab_name)], 10, 0, G_MAXINT64, -1)) != -1) { \
|
||||
NM_SET_OUT (_out_idx, _idx); \
|
||||
_good = TRUE; \
|
||||
} \
|
||||
_good; \
|
||||
})
|
||||
|
||||
static gboolean
|
||||
|
|
@ -919,10 +934,30 @@ _svKeyMatchesType (const char *key, SvKeyType match_key_type)
|
|||
if (IS_NUMBERED_TAG (key, "SRIOV_VF"))
|
||||
return TRUE;
|
||||
}
|
||||
if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTING_RULE4)) {
|
||||
if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE_", NULL))
|
||||
return TRUE;
|
||||
}
|
||||
if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTING_RULE6)) {
|
||||
if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE6_", NULL))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint64
|
||||
svNumberedParseKey (const char *key)
|
||||
{
|
||||
gint64 idx;
|
||||
|
||||
if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE_", &idx))
|
||||
return idx;
|
||||
if (IS_NUMBERED_TAG_PARSE (key, "ROUTING_RULE6_", &idx))
|
||||
return idx;
|
||||
return -1;
|
||||
}
|
||||
|
||||
GHashTable *
|
||||
svGetKeys (shvarFile *s, SvKeyType match_key_type)
|
||||
{
|
||||
|
|
@ -947,6 +982,42 @@ svGetKeys (shvarFile *s, SvKeyType match_key_type)
|
|||
return keys;
|
||||
}
|
||||
|
||||
static int
|
||||
_get_keys_sorted_cmp (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *k_a = *((const char *const*) a);
|
||||
const char *k_b = *((const char *const*) b);
|
||||
gint64 n_a;
|
||||
gint64 n_b;
|
||||
|
||||
n_a = svNumberedParseKey (k_a);
|
||||
n_b = svNumberedParseKey (k_b);
|
||||
NM_CMP_DIRECT (n_a, n_b);
|
||||
NM_CMP_RETURN (strcmp (k_a, k_b));
|
||||
nm_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char **
|
||||
svGetKeysSorted (shvarFile *s,
|
||||
SvKeyType match_key_type,
|
||||
guint *out_len)
|
||||
{
|
||||
gs_unref_hashtable GHashTable *keys_hash = NULL;
|
||||
|
||||
keys_hash = svGetKeys (s, match_key_type);
|
||||
if (!keys_hash) {
|
||||
NM_SET_OUT (out_len, 0);
|
||||
return NULL;
|
||||
}
|
||||
return (const char **) nm_utils_hash_keys_to_array (keys_hash,
|
||||
_get_keys_sorted_cmp,
|
||||
NULL,
|
||||
out_len);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ typedef enum {
|
|||
SV_KEY_TYPE_TC = (1LL << 3),
|
||||
SV_KEY_TYPE_USER = (1LL << 4),
|
||||
SV_KEY_TYPE_SRIOV_VF = (1LL << 5),
|
||||
SV_KEY_TYPE_ROUTING_RULE4 = (1LL << 6),
|
||||
SV_KEY_TYPE_ROUTING_RULE6 = (1LL << 7),
|
||||
} SvKeyType;
|
||||
|
||||
const char *svFileGetName (const shvarFile *s);
|
||||
|
|
@ -67,8 +69,14 @@ char *svGetValueStr_cp (shvarFile *s, const char *key);
|
|||
|
||||
int svParseBoolean (const char *value, int def);
|
||||
|
||||
gint64 svNumberedParseKey (const char *key);
|
||||
|
||||
GHashTable *svGetKeys (shvarFile *s, SvKeyType match_key_type);
|
||||
|
||||
const char **svGetKeysSorted (shvarFile *s,
|
||||
SvKeyType match_key_type,
|
||||
guint *out_len);
|
||||
|
||||
/* return TRUE if <key> resolves to any truth value (e.g. "yes", "y", "true")
|
||||
* return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
|
||||
* return <def> otherwise
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
TYPE=Ethernet
|
||||
PROXY_METHOD=none
|
||||
BROWSER_ONLY=no
|
||||
BOOTPROTO=dhcp
|
||||
DEFROUTE=yes
|
||||
IPV4_FAILURE_FATAL=no
|
||||
IPV6INIT=yes
|
||||
IPV6_AUTOCONF=yes
|
||||
IPV6_DEFROUTE=yes
|
||||
IPV6_FAILURE_FATAL=no
|
||||
IPV6_ADDR_GEN_MODE=stable-privacy
|
||||
ROUTING_RULE_1="priority 10 from 0.0.0.0/0 table 1"
|
||||
ROUTING_RULE_2="priority 10 to 192.167.8.0/24 table 2"
|
||||
ROUTING_RULE6_3="priority 10 from ::/0 table 10"
|
||||
ROUTING_RULE6_4="priority 10 to 1:2:3::5/24 table 22"
|
||||
ROUTING_RULE6_5="priority 10 to 1:3:3::5 table 55"
|
||||
NAME="Test Write Routing Rules"
|
||||
UUID=${UUID}
|
||||
ONBOOT=yes
|
||||
|
|
@ -4465,6 +4465,101 @@ test_write_wired_dhcp (void)
|
|||
nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
|
||||
}
|
||||
|
||||
static NMIPRoutingRule *
|
||||
_ip_routing_rule_new (int addr_family,
|
||||
const char *str)
|
||||
{
|
||||
NMIPRoutingRuleAsStringFlags flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_NONE;
|
||||
gs_free_error GError *local = NULL;
|
||||
NMIPRoutingRule *rule;
|
||||
|
||||
if (addr_family != AF_UNSPEC) {
|
||||
if (addr_family == AF_INET)
|
||||
flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET;
|
||||
else {
|
||||
g_assert (addr_family == AF_INET6);
|
||||
flags = NM_IP_ROUTING_RULE_AS_STRING_FLAGS_AF_INET6;
|
||||
}
|
||||
}
|
||||
|
||||
rule = nm_ip_routing_rule_from_string (str,
|
||||
NM_IP_ROUTING_RULE_AS_STRING_FLAGS_VALIDATE
|
||||
| flags,
|
||||
NULL,
|
||||
nmtst_get_rand_bool () ? &local : NULL);
|
||||
nmtst_assert_success (rule, local);
|
||||
|
||||
if (addr_family != AF_UNSPEC)
|
||||
g_assert_cmpint (nm_ip_routing_rule_get_addr_family (rule), ==, addr_family);
|
||||
return rule;
|
||||
}
|
||||
|
||||
static void
|
||||
_ip_routing_rule_add_to_setting (NMSettingIPConfig *s_ip,
|
||||
const char *str)
|
||||
{
|
||||
nm_auto_unref_ip_routing_rule NMIPRoutingRule *rule = NULL;
|
||||
|
||||
rule = _ip_routing_rule_new (nm_setting_ip_config_get_addr_family (s_ip), str);
|
||||
nm_setting_ip_config_add_routing_rule (s_ip, rule);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_routing_rules (void)
|
||||
{
|
||||
nmtst_auto_unlinkfile char *testfile = NULL;
|
||||
gs_unref_object NMConnection *connection = NULL;
|
||||
gs_unref_object NMConnection *reread = NULL;
|
||||
NMSettingConnection *s_con;
|
||||
NMSettingWired *s_wired;
|
||||
NMSettingIPConfig *s_ip4;
|
||||
NMSettingIPConfig *s_ip6;
|
||||
|
||||
connection = nm_simple_connection_new ();
|
||||
|
||||
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
||||
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_ID, "Test Write Routing Rules",
|
||||
NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (),
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
|
||||
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
||||
NULL);
|
||||
|
||||
s_wired = (NMSettingWired *) nm_setting_wired_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_wired));
|
||||
|
||||
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
|
||||
|
||||
g_object_set (s_ip4,
|
||||
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
||||
NULL);
|
||||
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
|
||||
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
||||
NULL);
|
||||
|
||||
_ip_routing_rule_add_to_setting (s_ip4, "pref 10 from 0.0.0.0/0 table 1");
|
||||
_ip_routing_rule_add_to_setting (s_ip4, "priority 10 to 192.167.8.0/24 table 2");
|
||||
_ip_routing_rule_add_to_setting (s_ip6, "pref 10 from ::/0 table 10");
|
||||
_ip_routing_rule_add_to_setting (s_ip6, "pref 10 from ::/0 to 1:2:3::5/24 table 22");
|
||||
_ip_routing_rule_add_to_setting (s_ip6, "pref 10 from ::/0 to 1:3:3::5/128 table 55");
|
||||
|
||||
nmtst_assert_connection_verifies (connection);
|
||||
|
||||
_writer_new_connec_exp (connection,
|
||||
TEST_SCRATCH_DIR,
|
||||
TEST_IFCFG_DIR"/ifcfg-Test_Write_Routing_Rules.cexpected",
|
||||
&testfile);
|
||||
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
|
||||
nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_wired_match (void)
|
||||
{
|
||||
|
|
@ -10200,6 +10295,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func (TPATH "wired/write-dhcp-plus-ip", test_write_wired_dhcp_plus_ip);
|
||||
g_test_add_func (TPATH "wired/write/dhcp-8021x-peap-mschapv2", test_write_wired_dhcp_8021x_peap_mschapv2);
|
||||
g_test_add_func (TPATH "wired/write/match", test_write_wired_match);
|
||||
g_test_add_func (TPATH "wired/write/routing-rules", test_write_routing_rules);
|
||||
|
||||
#define _add_test_write_wired_8021x_tls(testpath, scheme, flags) \
|
||||
nmtst_add_test_func (testpath, test_write_wired_8021x_tls, GINT_TO_POINTER (scheme), GINT_TO_POINTER (flags))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue