summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2020-06-10 13:54:54 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2020-06-12 16:04:06 +0200
commit808e837149978fc16b1aa90260600a764cecb284 (patch)
tree68cf7650a7a5cd0440a6c1fbad20cb90750c18d0
parentd13ca45ca265b67f7ccf0c17ae36dd804ddf7ef4 (diff)
downloadNetworkManager-808e837149978fc16b1aa90260600a764cecb284.tar.gz
all: add "path" property to the match setting
Add a new "path" property to the match setting, which can be used to restrict a connection to devices with a given hardware path. The new property is a list of patterns that are matched against the ID_PATH udev property of devices. ID_PATH represents the topological persistent path of a device and typically contains a subsystem string (pci, usb, platform, etc.) and a subsystem-specific identifier. Some examples of paths are: pci-0000:00:02.0 pci-0000:00:14.0-usb-0:5:1.0 platform-1c40000.ethernet systemd-networkd also has a "Path=" option to match a device by udev ID_PATH.
-rw-r--r--clients/common/nm-meta-setting-desc.c12
-rw-r--r--clients/common/settings-docs.h.in1
-rw-r--r--libnm-core/nm-setting-match.c216
-rw-r--r--libnm-core/nm-setting-match.h25
-rw-r--r--libnm/libnm.ver7
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c9
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c1
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h2
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c11
9 files changed, 277 insertions, 7 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 7951a2333c..dd5fd6f317 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -6265,6 +6265,18 @@ static const NMMetaPropertyInfo *const property_infos_MATCH[] = {
),
),
),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_MATCH_PATH,
+ .property_type = &_pt_multilist,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
+ PROPERTY_TYP_DATA_SUBTYPE (multilist,
+ .get_num_fcn_u = MULTILIST_GET_NUM_FCN_U (NMSettingMatch, nm_setting_match_get_num_paths),
+ .add2_fcn = MULTILIST_ADD2_FCN (NMSettingMatch, nm_setting_match_add_path),
+ .remove_by_idx_fcn_u = MULTILIST_REMOVE_BY_IDX_FCN_U (NMSettingMatch, nm_setting_match_remove_path),
+ .remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingMatch, nm_setting_match_remove_path_by_value),
+ .strsplit_with_spaces = TRUE,
+ ),
+ ),
+ ),
NULL
};
diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in
index 93472d160d..d9bb757515 100644
--- a/clients/common/settings-docs.h.in
+++ b/clients/common/settings-docs.h.in
@@ -283,6 +283,7 @@
#define DESCRIBE_DOC_NM_SETTING_MATCH_DRIVER N_("A list of driver names to match. Each element is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate driver name is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match.")
#define DESCRIBE_DOC_NM_SETTING_MATCH_INTERFACE_NAME N_("A list of interface names to match. Each element is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate interface name is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match.")
#define DESCRIBE_DOC_NM_SETTING_MATCH_KERNEL_COMMAND_LINE N_("A list of kernel command line arguments to match. This may be used to check whether a specific kernel command line option is set (or if prefixed with the exclamation mark unset). The argument must either be a single word, or an assignment (i.e. two words, separated \"=\"). In the former case the kernel command line is searched for the word appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is looked for with right and left hand side matching.")
+#define DESCRIBE_DOC_NM_SETTING_MATCH_PATH N_("A list of paths to match against the ID_PATH udev property of devices. ID_PATH represents the topological persistent path of a device. It typically contains a subsystem string (pci, usb, platform, etc.) and a subsystem-specific identifier. For PCI devices the path has the form \"pci-$domain:$bus:$device.$function\", where each variable is an hexadecimal value; for example \"pci-0000:0a:00.0\". The path of a device can be obtained with \"udevadm info /sys/class/net/$dev | grep ID_PATH=\" or by looking at the \"path\" property exported by NetworkManager (\"nmcli -f general.path device show $dev\"). Each element of the list is a shell wildcard pattern. When an element is prefixed with exclamation mark (!) the condition is inverted. A candidate path is considered matching when both these conditions are satisfied: (a) any of the elements not prefixed with '!' matches or there aren't such elements; (b) none of the elements prefixed with '!' match.")
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_DATAPATH_TYPE N_("The data path type. One of \"system\", \"netdev\" or empty.")
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_FAIL_MODE N_("The bridge failure mode. One of \"secure\", \"standalone\" or empty.")
#define DESCRIBE_DOC_NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE N_("Enable or disable multicast snooping.")
diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c
index a784df39bd..8fb513e545 100644
--- a/libnm-core/nm-setting-match.c
+++ b/libnm-core/nm-setting-match.c
@@ -22,6 +22,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch,
PROP_INTERFACE_NAME,
PROP_KERNEL_COMMAND_LINE,
PROP_DRIVER,
+ PROP_PATH,
);
/**
@@ -36,6 +37,7 @@ struct _NMSettingMatch {
GArray *interface_name;
GArray *kernel_command_line;
GArray *driver;
+ GArray *path;
};
struct _NMSettingMatchClass {
@@ -499,6 +501,156 @@ nm_setting_match_get_drivers (NMSettingMatch *setting, guint *length)
/*****************************************************************************/
+/**
+ * nm_setting_match_get_num_paths:
+ * @setting: the #NMSettingMatch
+ *
+ * Returns: the number of configured paths
+ *
+ * Since: 1.26
+ **/
+guint
+nm_setting_match_get_num_paths (NMSettingMatch *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), 0);
+
+ return nm_g_array_len (setting->path);
+}
+
+/**
+ * nm_setting_match_get_path:
+ * @setting: the #NMSettingMatch
+ * @idx: index number of the path to return
+ *
+ * Returns: the path at index @idx
+ *
+ * Since: 1.26
+ **/
+const char *
+nm_setting_match_get_path (NMSettingMatch *setting, guint idx)
+{
+ g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL);
+
+ g_return_val_if_fail (setting->path && idx < setting->path->len, NULL);
+
+ return g_array_index (setting->path, const char *, idx);
+}
+
+/**
+ * nm_setting_match_add_path:
+ * @setting: the #NMSettingMatch
+ * @path: the path to add
+ *
+ * Adds a new path to the setting.
+ *
+ * Since: 1.26
+ **/
+void
+nm_setting_match_add_path (NMSettingMatch *setting,
+ const char *path)
+{
+ g_return_if_fail (NM_IS_SETTING_MATCH (setting));
+ g_return_if_fail (path != NULL);
+ g_return_if_fail (path[0] != '\0');
+
+ nm_strvarray_add (nm_strvarray_ensure (&setting->path), path);
+ _notify (setting, PROP_PATH);
+}
+
+/**
+ * nm_setting_match_remove_path:
+ * @setting: the #NMSettingMatch
+ * @idx: index number of the path
+ *
+ * Removes the path at index @idx.
+ *
+ * Since: 1.26
+ **/
+void
+nm_setting_match_remove_path (NMSettingMatch *setting, guint idx)
+{
+ g_return_if_fail (NM_IS_SETTING_MATCH (setting));
+
+ g_return_if_fail (setting->path && idx < setting->path->len);
+
+ g_array_remove_index (setting->path, idx);
+ _notify (setting, PROP_PATH);
+}
+
+/**
+ * nm_setting_match_remove_path_by_value:
+ * @setting: the #NMSettingMatch
+ * @path: the path to remove
+ *
+ * Removes @path.
+ *
+ * Returns: %TRUE if the path was found and removed; %FALSE if it was not.
+ *
+ * Since: 1.26
+ **/
+gboolean
+nm_setting_match_remove_path_by_value (NMSettingMatch *setting,
+ const char *path)
+{
+ guint i;
+
+ g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+ g_return_val_if_fail (path[0] != '\0', FALSE);
+
+ if (!setting->path)
+ return FALSE;
+
+ for (i = 0; i < setting->path->len; i++) {
+ if (nm_streq (path, g_array_index (setting->path, const char *, i))) {
+ g_array_remove_index (setting->path, i);
+ _notify (setting, PROP_PATH);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_match_clear_paths:
+ * @setting: the #NMSettingMatch
+ *
+ * Removes all configured paths.
+ *
+ * Since: 1.26
+ **/
+void
+nm_setting_match_clear_paths (NMSettingMatch *setting)
+{
+ g_return_if_fail (NM_IS_SETTING_MATCH (setting));
+
+ if (nm_g_array_len (setting->path) != 0) {
+ nm_clear_pointer (&setting->path, g_array_unref);
+ _notify (setting, PROP_PATH);
+ }
+}
+
+/**
+ * nm_setting_match_get_paths:
+ * @setting: the #NMSettingMatch
+ * @length: (out) (allow-none): the length of the returned paths array.
+ *
+ * Returns all the paths.
+ *
+ * Returns: (transfer none) (array length=length): the configured paths.
+ *
+ * Since: 1.26
+ **/
+const char *const *
+nm_setting_match_get_paths (NMSettingMatch *setting, guint *length)
+{
+ g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL);
+
+ return nm_strvarray_get_strv (&setting->path, length);
+}
+
+/*****************************************************************************/
+
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -515,6 +667,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DRIVER:
g_value_set_boxed (value, nm_strvarray_get_strv (&self->driver, NULL));
break;
+ case PROP_PATH:
+ g_value_set_boxed (value, nm_strvarray_get_strv (&self->path, NULL));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -537,6 +692,9 @@ set_property (GObject *object, guint prop_id,
case PROP_DRIVER:
nm_strvarray_set_strv (&self->driver, g_value_get_boxed (value));
break;
+ case PROP_PATH:
+ nm_strvarray_set_strv (&self->path, g_value_get_boxed (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -613,6 +771,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
}
+ if (self->path) {
+ for (i = 0; i < self->path->len; i++) {
+ if (nm_str_is_empty (g_array_index (self->path, const char *, i))) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_MATCH_SETTING_NAME,
+ NM_SETTING_MATCH_PATH);
+ return FALSE;
+ }
+ }
+ }
+
return TRUE;
}
@@ -700,6 +872,50 @@ nm_setting_match_class_init (NMSettingMatchClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
+
+ /**
+ * NMSettingMatch:path
+ *
+ * A list of paths to match against the ID_PATH udev property of
+ * devices. ID_PATH represents the topological persistent path of a
+ * device. It typically contains a subsystem string (pci, usb, platform,
+ * etc.) and a subsystem-specific identifier.
+ *
+ * For PCI devices the path has the form
+ * "pci-$domain:$bus:$device.$function", where each variable is an
+ * hexadecimal value; for example "pci-0000:0a:00.0".
+ *
+ * The path of a device can be obtained with "udevadm info
+ * /sys/class/net/$dev | grep ID_PATH=" or by looking at the "path"
+ * property exported by NetworkManager ("nmcli -f general.path device
+ * show $dev").
+ *
+ * Each element of the list is a shell wildcard pattern. When an
+ * element is prefixed with exclamation mark (!) the condition is
+ * inverted.
+ *
+ * A candidate path is considered matching when both these
+ * conditions are satisfied: (a) any of the elements not prefixed with '!'
+ * matches or there aren't such elements; (b) none of the elements
+ * prefixed with '!' match.
+ *
+ * Since: 1.26
+ **/
+ /* ---ifcfg-rh---
+ * property: path
+ * variable: MATCH_PATH
+ * description: space-separated list of paths to match against the udev
+ * property ID_PATHS of devices
+ * example: MATCH_PATH="pci-0000:01:00.0 pci-0000:0c:00.0"
+ * ---end---
+ */
+ obj_properties[PROP_PATH] =
+ g_param_spec_boxed (NM_SETTING_MATCH_PATH, "", "",
+ G_TYPE_STRV,
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MATCH);
diff --git a/libnm-core/nm-setting-match.h b/libnm-core/nm-setting-match.h
index fa656037e0..63bd484780 100644
--- a/libnm-core/nm-setting-match.h
+++ b/libnm-core/nm-setting-match.h
@@ -23,9 +23,10 @@ G_BEGIN_DECLS
#define NM_SETTING_MATCH_SETTING_NAME "match"
-#define NM_SETTING_MATCH_INTERFACE_NAME "interface-name"
-#define NM_SETTING_MATCH_KERNEL_COMMAND_LINE "kernel-command-line"
-#define NM_SETTING_MATCH_DRIVER "driver"
+#define NM_SETTING_MATCH_INTERFACE_NAME "interface-name"
+#define NM_SETTING_MATCH_KERNEL_COMMAND_LINE "kernel-command-line"
+#define NM_SETTING_MATCH_DRIVER "driver"
+#define NM_SETTING_MATCH_PATH "path"
typedef struct _NMSettingMatchClass NMSettingMatchClass;
@@ -88,6 +89,24 @@ void nm_setting_match_clear_drivers (NMSettingMatch *setting);
NM_AVAILABLE_IN_1_26
const char *const *nm_setting_match_get_drivers (NMSettingMatch *setting, guint *length);
+
+NM_AVAILABLE_IN_1_26
+guint nm_setting_match_get_num_paths (NMSettingMatch *setting);
+NM_AVAILABLE_IN_1_26
+const char *nm_setting_match_get_path (NMSettingMatch *setting, guint idx);
+NM_AVAILABLE_IN_1_26
+void nm_setting_match_remove_path (NMSettingMatch *setting, guint idx);
+NM_AVAILABLE_IN_1_26
+gboolean nm_setting_match_remove_path_by_value (NMSettingMatch *setting,
+ const char *path);
+NM_AVAILABLE_IN_1_26
+void nm_setting_match_add_path (NMSettingMatch *setting,
+ const char *path);
+NM_AVAILABLE_IN_1_26
+void nm_setting_match_clear_paths (NMSettingMatch *setting);
+NM_AVAILABLE_IN_1_26
+const char *const *nm_setting_match_get_paths (NMSettingMatch *setting, guint *length);
+
G_END_DECLS
#endif /* NM_SETTING_MATCH_H */
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 8fdc3cc595..44437435d3 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1713,18 +1713,25 @@ global:
nm_setting_connection_get_mud_url;
nm_setting_match_add_driver;
nm_setting_match_add_kernel_command_line;
+ nm_setting_match_add_path;
nm_setting_match_clear_drivers;
nm_setting_match_clear_kernel_command_lines;
+ nm_setting_match_clear_paths;
nm_setting_match_get_driver;
nm_setting_match_get_drivers;
nm_setting_match_get_kernel_command_line;
nm_setting_match_get_kernel_command_lines;
nm_setting_match_get_num_drivers;
nm_setting_match_get_num_kernel_command_lines;
+ nm_setting_match_get_num_paths;
+ nm_setting_match_get_path;
+ nm_setting_match_get_paths;
nm_setting_match_remove_driver;
nm_setting_match_remove_driver_by_value;
nm_setting_match_remove_kernel_command_line;
nm_setting_match_remove_kernel_command_line_by_value;
+ nm_setting_match_remove_path;
+ nm_setting_match_remove_path_by_value;
nm_setting_option_clear_by_name;
nm_setting_option_get;
nm_setting_option_get_all_names;
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 4fee95c406..d65ae55551 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -1563,14 +1563,17 @@ make_match_setting (shvarFile *ifcfg)
gs_free char *value_ifn = NULL;
gs_free char *value_kcl = NULL;
gs_free char *value_d = NULL;
+ gs_free char *value_p = NULL;
const char *v;
v = svGetValueStr (ifcfg, "MATCH_INTERFACE_NAME", &value_ifn);
- make_match_setting_prop(v, &s_match, nm_setting_match_add_interface_name);
+ make_match_setting_prop (v, &s_match, nm_setting_match_add_interface_name);
v = svGetValueStr (ifcfg, "MATCH_KERNEL_COMMAND_LINE", &value_kcl);
- make_match_setting_prop(v, &s_match, nm_setting_match_add_kernel_command_line);
+ make_match_setting_prop (v, &s_match, nm_setting_match_add_kernel_command_line);
v = svGetValueStr (ifcfg, "MATCH_DRIVER", &value_d);
- make_match_setting_prop(v, &s_match, nm_setting_match_add_driver);
+ make_match_setting_prop (v, &s_match, nm_setting_match_add_driver);
+ v = svGetValueStr (ifcfg, "MATCH_PATH", &value_p);
+ make_match_setting_prop (v, &s_match, nm_setting_match_add_path);
return NM_SETTING (s_match);
}
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
index 188ae14527..d1500dbdb9 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
@@ -977,6 +977,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = {
_KEY_TYPE ("MATCH_DRIVER", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
_KEY_TYPE ("MATCH_INTERFACE_NAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
_KEY_TYPE ("MATCH_KERNEL_COMMAND_LINE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
+ _KEY_TYPE ("MATCH_PATH", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
_KEY_TYPE ("MDNS", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
_KEY_TYPE ("METRIC", NMS_IFCFG_KEY_TYPE_IS_NUMBERED ),
_KEY_TYPE ("MODE", NMS_IFCFG_KEY_TYPE_IS_PLAIN ),
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h
index 50b07d4a5d..459c5ae958 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h
@@ -33,7 +33,7 @@ typedef struct {
NMSIfcfgKeyTypeFlags key_flags;
} NMSIfcfgKeyTypeInfo;
-extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[239];
+extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[240];
const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info (const char *key, gssize *out_idx);
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 4f5d038d19..199e8e4e64 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -2438,6 +2438,17 @@ write_match_setting (NMConnection *connection, shvarFile *ifcfg)
}
svSetValueStr (ifcfg, "MATCH_KERNEL_COMMAND_LINE", str->str);
}
+
+ num = nm_setting_match_get_num_paths (s_match);
+ if (num > 0) {
+ nm_gstring_prepare (&str);
+ for (i = 0; i < num; i++) {
+ name = nm_setting_match_get_path (s_match, i);
+ nm_gstring_add_space_delimiter (str);
+ nm_utils_escaped_tokens_escape_gstr (name, NM_ASCII_SPACES, str);
+ }
+ svSetValueStr (ifcfg, "MATCH_PATH", str->str);
+ }
}
static void