Add a new "kernel-command-line" match option to nm-settings. It allows to disable a network connection configuration if a pattern is found or is not found in /proc/cmdline. --- clients/common/nm-meta-setting-desc.c | 45 +++++++ clients/common/settings-docs.h.in | 1 + libnm-core/nm-setting-match.c | 174 ++++++++++++++++++++++++++ libnm-core/nm-setting-match.h | 19 +++ libnm/libnm.ver | 7 ++ src/devices/nm-device.c | 16 ++- 6 files changed, 261 insertions(+), 1 deletion(-)
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index cd04e31d4..373841484 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -3440,6 +3440,35 @@ _get_fcn_match_interface_name (ARGS_GET_FCN) RETURN_STR_TO_FREE (g_string_free (str, FALSE)); } +static gconstpointer +_get_fcn_match_kernel_command_line (ARGS_GET_FCN) +{ + NMSettingMatch *s_match = NM_SETTING_MATCH (setting); + GString *str = NULL; + guint i, num; + + RETURN_UNSUPPORTED_GET_TYPE (); + + num = nm_setting_match_get_num_kernel_command_lines (s_match); + for (i = 0; i < num; i++) { + const char *name; + + name = nm_setting_match_get_kernel_command_line (s_match, i); + if (!name || !name[0]) + continue; + if (!str) + str = g_string_new (""); + else + g_string_append_c (str, ESCAPED_TOKENS_WITH_SPACES_DELIMTER); + nm_utils_escaped_tokens_escape_gstr (name, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS, str); + } + + NM_SET_OUT (out_is_default, num == 0); + if (!str) + return NULL; + RETURN_STR_TO_FREE (g_string_free (str, FALSE)); +} + static gconstpointer _get_fcn_olpc_mesh_ssid (ARGS_GET_FCN) { @@ -6107,6 +6136,22 @@ static const NMMetaPropertyInfo *const property_infos_MATCH[] = { ), ), ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MATCH_KERNEL_COMMAND_LINE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_match_kernel_command_line, + .set_fcn = _set_fcn_multilist, + .set_supports_remove = TRUE, + ), + .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_kernel_command_lines), + .add2_fcn = MULTILIST_ADD2_FCN (NMSettingMatch, nm_setting_match_add_kernel_command_line), + .remove_by_idx_fcn_s = MULTILIST_REMOVE_BY_IDX_FCN_S (NMSettingMatch, nm_setting_match_remove_kernel_command_line), + .remove_by_value_fcn = MULTILIST_REMOVE_BY_VALUE_FCN (NMSettingMatch, nm_setting_match_remove_kernel_command_line_by_value), + .strsplit_with_spaces = TRUE, + ), + ), + ), NULL }; diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index 69856394c..37f680133 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -263,6 +263,7 @@ #define DESCRIBE_DOC_NM_SETTING_MACVLAN_PROMISCUOUS N_("Whether the interface should be put in promiscuous mode.") #define DESCRIBE_DOC_NM_SETTING_MACVLAN_TAP N_("Whether the interface should be a MACVTAP.") #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 strings searched in the kernel command line arguments. When an element is prefixed with exclamation mark (!) the condition is inverted.") #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 2fbd0716b..a56539bba 100644 --- a/libnm-core/nm-setting-match.c +++ b/libnm-core/nm-setting-match.c @@ -20,6 +20,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch, PROP_INTERFACE_NAME, + PROP_KERNEL_COMMAND_LINE, ); /** @@ -32,6 +33,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch, struct _NMSettingMatch { NMSetting parent; GPtrArray *interface_name; + GPtrArray *kernel_command_line; }; struct _NMSettingMatchClass { @@ -190,6 +192,154 @@ nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length) /*****************************************************************************/ +/** + * nm_setting_match_get_num_kernel_command_lines: + * @setting: the #NMSettingMatch + * + * Returns: the number of configured kernel command line arguments + * + * Since: 1.24 + **/ +guint +nm_setting_match_get_num_kernel_command_lines (NMSettingMatch *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), 0); + + return setting->kernel_command_line->len; +} + +/** + * nm_setting_match_get_kernel_command_line: + * @setting: the #NMSettingMatch + * @idx: index number of the kernel command line argument to return + * + * Returns: the kernel command line argument at index @idx + * + * Since: 1.24 + **/ +const char * +nm_setting_match_get_kernel_command_line (NMSettingMatch *setting, int idx) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL); + + g_return_val_if_fail (idx >= 0 && idx < setting->kernel_command_line->len, NULL); + + return setting->kernel_command_line->pdata[idx]; +} + +/** + * nm_setting_match_add_kernel_command_line: + * @setting: the #NMSettingMatch + * @kernel_command_line: the kernel command line argument to add + * + * Adds a new kernel command line argument to the setting. + * + * Since: 1.24 + **/ +void +nm_setting_match_add_kernel_command_line (NMSettingMatch *setting, + const char *kernel_command_line) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + g_return_if_fail (kernel_command_line != NULL); + g_return_if_fail (kernel_command_line[0] != '\0'); + + g_ptr_array_add (setting->kernel_command_line, g_strdup (kernel_command_line)); + _notify (setting, PROP_KERNEL_COMMAND_LINE); +} + +/** + * nm_setting_match_remove_kernel_command_line: + * @setting: the #NMSettingMatch + * @idx: index number of the kernel command line argument + * + * Removes the ikernel command line argument at index @idx. + * + * Since: 1.24 + **/ +void +nm_setting_match_remove_kernel_command_line (NMSettingMatch *setting, int idx) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + + g_return_if_fail (idx >= 0 && idx < setting->kernel_command_line->len); + + g_ptr_array_remove_index (setting->kernel_command_line, idx); + _notify (setting, PROP_KERNEL_COMMAND_LINE); +} + +/** + * nm_setting_match_remove_kernel_command_line_by_value: + * @setting: the #NMSettingMatch + * @kernel_command_line: the kernel command line argument name to remove + * + * Removes @kernel_command_line. + * + * Returns: %TRUE if the kernel command line argument was found and removed; %FALSE if it was not. + * + * Since: 1.24 + **/ +gboolean +nm_setting_match_remove_kernel_command_line_by_value (NMSettingMatch *setting, + const char *kernel_command_line) +{ + guint i; + + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), FALSE); + g_return_val_if_fail (kernel_command_line != NULL, FALSE); + g_return_val_if_fail (kernel_command_line[0] != '\0', FALSE); + + for (i = 0; i < setting->kernel_command_line->len; i++) { + if (nm_streq (kernel_command_line, setting->kernel_command_line->pdata[i])) { + g_ptr_array_remove_index (setting->kernel_command_line, i); + _notify (setting, PROP_KERNEL_COMMAND_LINE); + return TRUE; + } + } + return FALSE; +} + +/** + * nm_setting_match_clear_kernel_command_lines: + * @setting: the #NMSettingMatch + * + * Removes all configured kernel command line arguments. + * + * Since: 1.24 + **/ +void +nm_setting_match_clear_kernel_command_lines (NMSettingMatch *setting) +{ + g_return_if_fail (NM_IS_SETTING_MATCH (setting)); + + if (setting->kernel_command_line->len != 0) { + g_ptr_array_set_size (setting->kernel_command_line, 0); + _notify (setting, PROP_KERNEL_COMMAND_LINE); + } +} + +/** + * nm_setting_match_get_kernel_command_lines: + * @setting: the #NMSettingMatch + * + * Returns all the interface names. + * + * Returns: (transfer none): the configured interface names. + * + * Since: 1.24 + **/ +const char *const * +nm_setting_match_get_kernel_command_lines (NMSettingMatch *setting, guint *length) +{ + g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL); + g_return_val_if_fail (length, NULL); + + NM_SET_OUT (length, setting->kernel_command_line->len); + return (const char *const *) setting->kernel_command_line->pdata; +} + +/*****************************************************************************/ + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -200,6 +350,9 @@ get_property (GObject *object, guint prop_id, case PROP_INTERFACE_NAME: g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (self->interface_name)); break; + case PROP_KERNEL_COMMAND_LINE: + g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (self->kernel_command_line)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -217,6 +370,10 @@ set_property (GObject *object, guint prop_id, g_ptr_array_unref (self->interface_name); self->interface_name = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value)); break; + case PROP_KERNEL_COMMAND_LINE: + g_ptr_array_unref (self->kernel_command_line); + self->kernel_command_line = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -229,6 +386,7 @@ static void nm_setting_match_init (NMSettingMatch *setting) { setting->interface_name = g_ptr_array_new_with_free_func (g_free); + setting->kernel_command_line = g_ptr_array_new_with_free_func (g_free); } /** @@ -252,6 +410,7 @@ finalize (GObject *object) NMSettingMatch *self = NM_SETTING_MATCH (object); g_ptr_array_unref (self->interface_name); + g_ptr_array_unref (self->kernel_command_line); G_OBJECT_CLASS (nm_setting_match_parent_class)->finalize (object); } @@ -287,6 +446,21 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /** + * NMSettingMatch:kernel-command-line + * + * A list of strings searched in the kernel command line arguments. When an + * element is prefixed with exclamation mark (!) the condition is inverted. + * + * Since: 1.24 + **/ + obj_properties[PROP_KERNEL_COMMAND_LINE] = + g_param_spec_boxed (NM_SETTING_MATCH_KERNEL_COMMAND_LINE, "", "", + 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 e15911adb..f9b493471 100644 --- a/libnm-core/nm-setting-match.h +++ b/libnm-core/nm-setting-match.h @@ -24,6 +24,7 @@ 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" typedef struct _NMSettingMatchClass NMSettingMatchClass; @@ -49,6 +50,24 @@ NM_AVAILABLE_IN_1_14 void nm_setting_match_clear_interface_names (NMSettingMatch *setting); NM_AVAILABLE_IN_1_14 const char *const *nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length); + + +NM_AVAILABLE_IN_1_24 +guint nm_setting_match_get_num_kernel_command_lines (NMSettingMatch *setting); +NM_AVAILABLE_IN_1_24 +const char *nm_setting_match_get_kernel_command_line (NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_24 +void nm_setting_match_remove_kernel_command_line (NMSettingMatch *setting, int idx); +NM_AVAILABLE_IN_1_24 +gboolean nm_setting_match_remove_kernel_command_line_by_value (NMSettingMatch *setting, + const char *kernel_command_line); +NM_AVAILABLE_IN_1_24 +void nm_setting_match_add_kernel_command_line (NMSettingMatch *setting, + const char *kernel_command_line); +NM_AVAILABLE_IN_1_24 +void nm_setting_match_clear_kernel_command_lines (NMSettingMatch *setting); +NM_AVAILABLE_IN_1_24 +const char *const *nm_setting_match_get_kernel_command_lines (NMSettingMatch *setting, guint *length); G_END_DECLS #endif /* NM_SETTING_MATCH_H */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 9229a1fc7..5d7873f4d 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1411,6 +1411,13 @@ global: nm_setting_match_get_type; nm_setting_match_remove_interface_name; nm_setting_match_remove_interface_name_by_value; + nm_setting_match_add_kernel_command_line; + nm_setting_match_clear_kernel_command_lines; + nm_setting_match_get_kernel_command_line; + nm_setting_match_get_kernel_command_lines; + nm_setting_match_get_num_kernel_command_lines; + nm_setting_match_remove_kernel_command_line; + nm_setting_match_remove_kernel_command_line_by_value; nm_setting_sriov_add_vf; nm_setting_sriov_clear_vfs; nm_setting_sriov_get_autoprobe_drivers; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 5d0774e91..2a0a58792 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -5994,7 +5994,6 @@ check_connection_compatible (NMDevice *self, NMConnection *connection, GError ** gs_free_error GError *local = NULL; gs_free char *conn_iface = NULL; NMDeviceClass *klass; - const char *const *patterns; NMSettingMatch *s_match; klass = NM_DEVICE_GET_CLASS (self); @@ -6037,7 +6036,10 @@ check_connection_compatible (NMDevice *self, NMConnection *connection, GError ** s_match = (NMSettingMatch *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MATCH); if (s_match) { + const char *const *patterns; guint num_patterns = 0; + gs_free char *proc_cmdline = NULL; + gsize proc_cmdline_len = 0; patterns = nm_setting_match_get_interface_names (s_match, &num_patterns); if (!nm_wildcard_match_check (device_iface, patterns, num_patterns)) { @@ -6045,6 +6047,18 @@ check_connection_compatible (NMDevice *self, NMConnection *connection, GError ** "device does not satisfy match.interface-name property"); return FALSE; } + + patterns = nm_setting_match_get_kernel_command_lines (s_match, &num_patterns); + if (g_file_get_contents ("/proc/cmdline", &proc_cmdline, &proc_cmdline_len, NULL)) { + if (!nm_wildcard_match_check (proc_cmdline, patterns, num_patterns)) { + nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "device does not satisfy match.kernel-command-line property"); + _LOGD (LOGD_DEVICE, "does not satisfy match.kernel-command-line: %s", proc_cmdline); + return FALSE; + } else { + _LOGD (LOGD_DEVICE, "satisfies match.kernel-command-line: %s", proc_cmdline); + } + } } return TRUE; -- 2.24.1 _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org https://mail.gnome.org/mailman/listinfo/networkmanager-list