diff options
Diffstat (limited to 'libnm-core')
66 files changed, 4667 insertions, 986 deletions
diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h index 620e6a81..ee2d7264 100644 --- a/libnm-core/nm-connection-private.h +++ b/libnm-core/nm-connection-private.h @@ -29,7 +29,15 @@ NMSetting *_nm_connection_find_base_type_setting (NMConnection *connect const char *_nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_port); +const char *_nm_connection_detect_bluetooth_type (NMConnection *self); + gboolean _nm_connection_verify_required_interface_name (NMConnection *connection, GError **error); +int _nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, + NMConnection *connection, + gboolean normalize, + gboolean *out_modified, + GError **error); + #endif /* __NM_CONNECTION_PRIVATE_H__ */ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index c1b75068..d5e28f7b 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -93,10 +93,16 @@ _setting_release (gpointer key, gpointer value, gpointer user_data) static void _nm_connection_add_setting (NMConnection *connection, NMSetting *setting) { - NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); - const char *name = G_OBJECT_TYPE_NAME (setting); + NMConnectionPrivate *priv; + const char *name; NMSetting *s_old; + nm_assert (NM_IS_CONNECTION (connection)); + nm_assert (NM_IS_SETTING (setting)); + + priv = NM_CONNECTION_GET_PRIVATE (connection); + name = G_OBJECT_TYPE_NAME (setting); + if ((s_old = g_hash_table_lookup (priv->settings, (gpointer) name))) g_signal_handlers_disconnect_by_func (s_old, setting_changed_cb, connection); g_hash_table_insert (priv->settings, (gpointer) name, setting); @@ -160,6 +166,24 @@ nm_connection_remove_setting (NMConnection *connection, GType setting_type) _nm_connection_remove_setting (connection, setting_type); } +static gpointer +_connection_get_setting (NMConnection *connection, GType setting_type) +{ + nm_assert (NM_IS_CONNECTION (connection)); + nm_assert (g_type_is_a (setting_type, NM_TYPE_SETTING)); + + return g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings, + g_type_name (setting_type)); +} + +static gpointer +_connection_get_setting_check (NMConnection *connection, GType setting_type) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + return _connection_get_setting (connection, setting_type); +} + /** * nm_connection_get_setting: * @connection: a #NMConnection @@ -174,11 +198,9 @@ nm_connection_remove_setting (NMConnection *connection, GType setting_type) NMSetting * nm_connection_get_setting (NMConnection *connection, GType setting_type) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL); - return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings, - g_type_name (setting_type)); + return _connection_get_setting_check (connection, setting_type); } /** @@ -198,11 +220,9 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name) GType type; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (name != NULL, NULL); type = nm_setting_lookup_type (name); - - return type ? nm_connection_get_setting (connection, type) : NULL; + return type ? _connection_get_setting (connection, type) : NULL; } static gboolean @@ -496,7 +516,7 @@ nm_connection_compare (NMConnection *a, } -static void +static gboolean diff_one_connection (NMConnection *a, NMConnection *b, NMSettingCompareFlags flags, @@ -506,6 +526,7 @@ diff_one_connection (NMConnection *a, NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (a); GHashTableIter iter; NMSetting *a_setting = NULL; + gboolean diff_found = FALSE; g_hash_table_iter_init (&iter, priv->settings); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &a_setting)) { @@ -521,11 +542,14 @@ diff_one_connection (NMConnection *a, if (results) new_results = FALSE; - if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results)) { - if (new_results) - g_hash_table_insert (diffs, g_strdup (setting_name), results); - } + if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results)) + diff_found = TRUE; + + if (new_results && results) + g_hash_table_insert (diffs, g_strdup (setting_name), results); } + + return diff_found; } /** @@ -554,12 +578,11 @@ nm_connection_diff (NMConnection *a, GHashTable **out_settings) { GHashTable *diffs; + gboolean diff_found = FALSE; g_return_val_if_fail (NM_IS_CONNECTION (a), FALSE); - g_return_val_if_fail (out_settings != NULL, FALSE); - g_return_val_if_fail (*out_settings == NULL, FALSE); - if (b) - g_return_val_if_fail (NM_IS_CONNECTION (b), FALSE); + g_return_val_if_fail (!out_settings || !*out_settings, FALSE); + g_return_val_if_fail (!b || NM_IS_CONNECTION (b), FALSE); if (a == b) return TRUE; @@ -567,16 +590,22 @@ nm_connection_diff (NMConnection *a, diffs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy); /* Diff A to B, then B to A to capture keys in B that aren't in A */ - diff_one_connection (a, b, flags, FALSE, diffs); - if (b) - diff_one_connection (b, a, flags, TRUE, diffs); + if (diff_one_connection (a, b, flags, FALSE, diffs)) + diff_found = TRUE; + if ( b + && diff_one_connection (b, a, flags, TRUE, diffs)) + diff_found = TRUE; - if (g_hash_table_size (diffs) == 0) + nm_assert (diff_found == (g_hash_table_size (diffs) != 0)); + + if (g_hash_table_size (diffs) == 0) { g_hash_table_destroy (diffs); - else - *out_settings = diffs; + diffs = NULL; + } + + NM_SET_OUT (out_settings, diffs); - return *out_settings ? FALSE : TRUE; + return !diff_found; } NMSetting * @@ -585,19 +614,31 @@ _nm_connection_find_base_type_setting (NMConnection *connection) NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); GHashTableIter iter; NMSetting *setting = NULL, *s_iter; + NMSettingPriority setting_prio, s_iter_prio; g_hash_table_iter_init (&iter, priv->settings); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) { - if (!_nm_setting_is_base_type (s_iter)) + s_iter_prio = _nm_setting_get_base_type_priority (s_iter); + if (s_iter_prio == NM_SETTING_PRIORITY_INVALID) continue; if (setting) { - /* FIXME: currently, if there is more than one matching base type, - * we cannot detect the base setting. - * See: https://bugzilla.gnome.org/show_bug.cgi?id=696936#c8 */ - return NULL; + if (s_iter_prio > setting_prio) { + continue; + } else if (s_iter_prio == setting_prio) { + NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); + const char *type; + + if (s_con) { + type = nm_setting_connection_get_connection_type (s_con); + if (type) + return nm_connection_get_setting_by_name (connection, type); + } + return NULL; + } } setting = s_iter; + setting_prio = s_iter_prio; } return setting; } @@ -652,6 +693,26 @@ _normalize_connection_type (NMConnection *self) } const char * +_nm_connection_detect_bluetooth_type (NMConnection *self) +{ + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self); + + if ( s_bt + && nm_setting_bluetooth_get_connection_type (s_bt)) { + if ( nm_connection_get_setting_gsm (self) + || nm_connection_get_setting_cdma (self)) + return NM_SETTING_BLUETOOTH_TYPE_DUN; + if (nm_connection_get_setting_bridge (self)) + return NM_SETTING_BLUETOOTH_TYPE_NAP; + return NM_SETTING_BLUETOOTH_TYPE_PANU; + } + + /* NULL means the connection is not a bluetooth type, or it needs + * no normalization, as the type is set explicitly. */ + return NULL; +} + +const char * _nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_port) { NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); @@ -668,6 +729,10 @@ _nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_po i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME; else if (!strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME)) i_slave_type = NM_SETTING_TEAM_SETTING_NAME; + else if (!strcmp (name, NM_SETTING_OVS_PORT_SETTING_NAME)) + i_slave_type = NM_SETTING_OVS_BRIDGE_SETTING_NAME; + else if (!strcmp (name, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) + i_slave_type = NM_SETTING_OVS_PORT_SETTING_NAME; else continue; @@ -748,9 +813,20 @@ _normalize_ethernet_link_neg (NMConnection *self) } static gboolean +_without_ip_config (NMConnection *self) +{ + const char *connection_type = nm_connection_get_connection_type (self); + + g_return_val_if_fail (connection_type, FALSE); + if (strcmp (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0) + return FALSE; + + return !!nm_setting_connection_get_master (nm_connection_get_setting_connection (self)); +} + +static gboolean _normalize_ip_config (NMConnection *self, GHashTable *parameters) { - NMSettingConnection *s_con = nm_connection_get_setting_connection (self); const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; const char *default_ip6_method = NULL; NMSettingIPConfig *s_ip4, *s_ip6; @@ -768,7 +844,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) s_ip6 = nm_connection_get_setting_ip6_config (self); s_proxy = nm_connection_get_setting_proxy (self); - if (nm_setting_connection_get_master (s_con)) { + if (_without_ip_config (self)) { /* Slave connections don't have IP configuration. */ if (s_ip4) @@ -1021,15 +1097,62 @@ _normalize_team_port_config (NMConnection *self, GHashTable *parameters) } static gboolean +_normalize_bluetooth_type (NMConnection *self, GHashTable *parameters) +{ + const char *type = _nm_connection_detect_bluetooth_type (self); + + if (type) { + g_object_set (nm_connection_get_setting_bluetooth (self), + NM_SETTING_BLUETOOTH_TYPE, type, + NULL); + return TRUE; + } + return FALSE; +} + +static gboolean +_normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters) +{ + NMSettingOvsInterface *s_ovs_interface = nm_connection_get_setting_ovs_interface (self); + gboolean modified; + int v; + + if (!s_ovs_interface) + return FALSE; + + v = _nm_setting_ovs_interface_verify_interface_type (s_ovs_interface, + self, + TRUE, + &modified, + NULL); + if (v != TRUE) + g_return_val_if_reached (modified); + + return modified; +} + +static gboolean _normalize_required_settings (NMConnection *self, GHashTable *parameters) { + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self); + NMSetting *s_bridge; + gboolean changed = FALSE; + if (nm_connection_get_setting_vlan (self)) { if (!nm_connection_get_setting_wired (self)) { nm_connection_add_setting (self, nm_setting_wired_new ()); - return TRUE; + changed = TRUE; } } - return FALSE; + if (s_bt && nm_streq0 (nm_setting_bluetooth_get_connection_type (s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP)) { + if (!nm_connection_get_setting_bridge (self)) { + s_bridge = nm_setting_bridge_new (); + g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); + nm_connection_add_setting (self, s_bridge); + changed = TRUE; + } + } + return changed; } static gboolean @@ -1165,40 +1288,42 @@ _nm_connection_verify (NMConnection *connection, GError **error) s_ip6 = nm_connection_get_setting_ip6_config (connection); s_proxy = nm_connection_get_setting_proxy (connection); - if (nm_setting_connection_get_master (s_con)) { - if ( NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS, - NM_SETTING_VERIFY_NORMALIZABLE) - && (s_ip4 || s_ip6 || s_proxy)) { - g_clear_error (&normalizable_error); - g_set_error_literal (&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_SETTING, - _("setting not allowed in slave connection")); - g_prefix_error (&normalizable_error, "%s: ", - s_ip4 - ? NM_SETTING_IP4_CONFIG_SETTING_NAME - : (s_ip6 - ? NM_SETTING_IP6_CONFIG_SETTING_NAME - : NM_SETTING_PROXY_SETTING_NAME)); - /* having a slave with IP config *was* and is a verify() error. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; - } - } else { - if ( NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS) - && (!s_ip4 || !s_ip6 || !s_proxy)) { - g_set_error_literal (&normalizable_error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_SETTING, - _("setting is required for non-slave connections")); - g_prefix_error (&normalizable_error, "%s: ", - !s_ip4 - ? NM_SETTING_IP4_CONFIG_SETTING_NAME - : (!s_ip6 - ? NM_SETTING_IP6_CONFIG_SETTING_NAME - : NM_SETTING_PROXY_SETTING_NAME)); - /* having a master without IP config was not a verify() error, accept - * it for backward compatibility. */ - normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + nm_assert (normalizable_error_type != NM_SETTING_VERIFY_ERROR); + if (NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS, + NM_SETTING_VERIFY_NORMALIZABLE)) { + if (_without_ip_config (connection)) { + if (s_ip4 || s_ip6 || s_proxy) { + g_clear_error (&normalizable_error); + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("setting not allowed in slave connection")); + g_prefix_error (&normalizable_error, "%s: ", + s_ip4 + ? NM_SETTING_IP4_CONFIG_SETTING_NAME + : (s_ip6 + ? NM_SETTING_IP6_CONFIG_SETTING_NAME + : NM_SETTING_PROXY_SETTING_NAME)); + /* having a slave with IP config *was* and is a verify() error. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + } else { + if ( normalizable_error_type == NM_SETTING_VERIFY_SUCCESS + && (!s_ip4 || !s_ip6 || !s_proxy)) { + g_set_error_literal (&normalizable_error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("setting is required for non-slave connections")); + g_prefix_error (&normalizable_error, "%s: ", + !s_ip4 + ? NM_SETTING_IP4_CONFIG_SETTING_NAME + : (!s_ip6 + ? NM_SETTING_IP6_CONFIG_SETTING_NAME + : NM_SETTING_PROXY_SETTING_NAME)); + /* having a master without IP config was not a verify() error, accept + * it for backward compatibility. */ + normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE; + } } } @@ -1309,6 +1434,8 @@ nm_connection_normalize (NMConnection *connection, was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters); was_modified |= _normalize_team_config (connection, parameters); was_modified |= _normalize_team_port_config (connection, parameters); + was_modified |= _normalize_bluetooth_type (connection, parameters); + was_modified |= _normalize_ovs_interface_type (connection, parameters); /* Verify anew. */ success = _nm_connection_verify (connection, error); @@ -1326,6 +1453,7 @@ nm_connection_normalize (NMConnection *connection, NM_CONNECTION_ERROR_FAILED, _("Unexpected failure to normalize the connection")); } + g_warning ("connection did not verify after normalization: %s", error ? (*error)->message : "??"); g_return_val_if_reached (FALSE); } @@ -1640,19 +1768,9 @@ nm_connection_to_dbus (NMConnection *connection, gboolean nm_connection_is_type (NMConnection *connection, const char *type) { - NMSettingConnection *s_con; - const char *type2; - - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - g_return_val_if_fail (type != NULL, FALSE); + g_return_val_if_fail (type, FALSE); - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) - return FALSE; - - type2 = nm_setting_connection_get_connection_type (s_con); - - return (g_strcmp0 (type2, type) == 0); + return nm_streq0 (type, nm_connection_get_connection_type (connection)); } static int @@ -1669,52 +1787,82 @@ _for_each_sort (NMSetting **p_a, NMSetting **p_b, void *unused) } /** - * nm_connection_for_each_setting_value: - * @connection: the #NMConnection - * @func: (scope call): user-supplied function called for each setting's property - * @user_data: user data passed to @func at each invocation + * nm_connection_get_settings: + * @connection: the #NMConnection instance + * @out_length: (allow-none): (out): the length of the returned array * - * Iterates over the properties of each #NMSetting object in the #NMConnection, - * calling the supplied user function for each property. - **/ -void -nm_connection_for_each_setting_value (NMConnection *connection, - NMSettingValueIterFn func, - gpointer user_data) + * Retrieves the settings in @connection. + * + * The returned array is %NULL-terminated. + * + * Returns: (array length=out_length) (transfer container): a + * %NULL-terminated array containing every setting of + * @connection. + * If the connection has no settings, %NULL is returned. + * + * Since: 1.10 + */ +NMSetting ** +nm_connection_get_settings (NMConnection *connection, + guint *out_length) { NMConnectionPrivate *priv; - gs_free NMSetting **arr_free = NULL; - NMSetting *arr_temp[20], **arr; + NMSetting **arr; GHashTableIter iter; - gpointer value; + NMSetting *setting; guint i, size; - g_return_if_fail (NM_IS_CONNECTION (connection)); - g_return_if_fail (func != NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); priv = NM_CONNECTION_GET_PRIVATE (connection); size = g_hash_table_size (priv->settings); - if (!size) - return; - if (size > G_N_ELEMENTS (arr_temp)) - arr = arr_free = g_new (NMSetting *, size); - else - arr = arr_temp; + if (!size) { + NM_SET_OUT (out_length, 0); + return NULL; + } + + arr = g_new (NMSetting *, size + 1); g_hash_table_iter_init (&iter, priv->settings); - for (i = 0; g_hash_table_iter_next (&iter, NULL, &value); i++) - arr[i] = NM_SETTING (value); - g_assert (i == size); + for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &setting); i++) + arr[i] = setting; + nm_assert (i == size); + arr[size] = NULL; /* sort the settings. This has an effect on the order in which keyfile * prints them. */ if (size > 1) g_qsort_with_data (arr, size, sizeof (NMSetting *), (GCompareDataFunc) _for_each_sort, NULL); - for (i = 0; i < size; i++) - nm_setting_enumerate_values (arr[i], func, user_data); + NM_SET_OUT (out_length, size); + return arr; +} + +/** + * nm_connection_for_each_setting_value: + * @connection: the #NMConnection + * @func: (scope call): user-supplied function called for each setting's property + * @user_data: user data passed to @func at each invocation + * + * Iterates over the properties of each #NMSetting object in the #NMConnection, + * calling the supplied user function for each property. + **/ +void +nm_connection_for_each_setting_value (NMConnection *connection, + NMSettingValueIterFn func, + gpointer user_data) +{ + gs_free NMSetting **settings = NULL; + guint i, length = 0; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (func); + + settings = nm_connection_get_settings (connection, &length); + for (i = 0; i < length; i++) + nm_setting_enumerate_values (settings[i], func, user_data); } /** @@ -1764,10 +1912,7 @@ nm_connection_set_path (NMConnection *connection, const char *path) priv = NM_CONNECTION_GET_PRIVATE (connection); g_free (priv->path); - priv->path = NULL; - - if (path) - priv->path = g_strdup (path); + priv->path = g_strdup (path); } /** @@ -1805,10 +1950,7 @@ nm_connection_get_interface_name (NMConnection *connection) { NMSettingConnection *s_con; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - s_con = nm_connection_get_setting_connection (connection); - return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL; } @@ -1818,6 +1960,9 @@ _nm_connection_verify_required_interface_name (NMConnection *connection, { const char *interface_name; + if (!connection) + return TRUE; + interface_name = nm_connection_get_interface_name (connection); if (interface_name) return TRUE; @@ -1843,13 +1988,8 @@ nm_connection_get_uuid (NMConnection *connection) { NMSettingConnection *s_con; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) - return NULL; - - return nm_setting_connection_get_uuid (s_con); + return s_con ? nm_setting_connection_get_uuid (s_con) : NULL; } /** @@ -1865,13 +2005,8 @@ nm_connection_get_id (NMConnection *connection) { NMSettingConnection *s_con; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) - return NULL; - - return nm_setting_connection_get_id (s_con); + return s_con ? nm_setting_connection_get_id (s_con) : NULL; } /** @@ -1887,13 +2022,8 @@ nm_connection_get_connection_type (NMConnection *connection) { NMSettingConnection *s_con; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - s_con = nm_connection_get_setting_connection (connection); - if (!s_con) - return NULL; - - return nm_setting_connection_get_connection_type (s_con); + return s_con ? nm_setting_connection_get_connection_type (s_con) : NULL; } /** @@ -1911,7 +2041,8 @@ nm_connection_is_virtual (NMConnection *connection) const char *type; type = nm_connection_get_connection_type (connection); - g_return_val_if_fail (type != NULL, FALSE); + if (!type) + return FALSE; if ( !strcmp (type, NM_SETTING_BOND_SETTING_NAME) || !strcmp (type, NM_SETTING_DUMMY_SETTING_NAME) @@ -1922,6 +2053,9 @@ nm_connection_is_virtual (NMConnection *connection) || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME) || !strcmp (type, NM_SETTING_MACSEC_SETTING_NAME) || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME) + || !strcmp (type, NM_SETTING_OVS_BRIDGE_SETTING_NAME) + || !strcmp (type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) + || !strcmp (type, NM_SETTING_OVS_PORT_SETTING_NAME) || !strcmp (type, NM_SETTING_VXLAN_SETTING_NAME)) return TRUE; @@ -1929,8 +2063,17 @@ nm_connection_is_virtual (NMConnection *connection) NMSettingInfiniband *s_ib; s_ib = nm_connection_get_setting_infiniband (connection); - g_return_val_if_fail (s_ib != NULL, FALSE); - return nm_setting_infiniband_get_virtual_interface_name (s_ib) != NULL; + return s_ib && nm_setting_infiniband_get_virtual_interface_name (s_ib); + } + + if (nm_streq (type, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return !!_nm_connection_get_setting_bluetooth_for_nap (connection); + + if (nm_streq (type, NM_SETTING_PPPOE_SETTING_NAME)) { + NMSettingPppoe *s_pppoe; + + s_pppoe = nm_connection_get_setting_pppoe (connection); + return !!nm_setting_pppoe_get_parent (s_pppoe); } return FALSE; @@ -1953,10 +2096,11 @@ nm_connection_get_virtual_device_description (NMConnection *connection) const char *type; const char *iface = NULL, *display_type = NULL; - iface = nm_connection_get_interface_name (connection); - type = nm_connection_get_connection_type (connection); - g_return_val_if_fail (type != NULL, FALSE); + if (!type) + return NULL; + + iface = nm_connection_get_interface_name (connection); if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) display_type = _("Bond"); @@ -1991,9 +2135,7 @@ nm_connection_get_virtual_device_description (NMConnection *connection) NMSetting8021x * nm_connection_get_setting_802_1x (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_802_1X); } /** @@ -2007,9 +2149,7 @@ nm_connection_get_setting_802_1x (NMConnection *connection) NMSettingBluetooth * nm_connection_get_setting_bluetooth (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_BLUETOOTH); } /** @@ -2023,9 +2163,7 @@ nm_connection_get_setting_bluetooth (NMConnection *connection) NMSettingBond * nm_connection_get_setting_bond (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_BOND); } /** @@ -2039,9 +2177,7 @@ nm_connection_get_setting_bond (NMConnection *connection) NMSettingTeam * nm_connection_get_setting_team (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingTeam *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_TEAM); } /** @@ -2055,9 +2191,7 @@ nm_connection_get_setting_team (NMConnection *connection) NMSettingTeamPort * nm_connection_get_setting_team_port (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingTeamPort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_TEAM_PORT); } /** @@ -2071,9 +2205,7 @@ nm_connection_get_setting_team_port (NMConnection *connection) NMSettingBridge * nm_connection_get_setting_bridge (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingBridge *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_BRIDGE); } /** @@ -2087,9 +2219,7 @@ nm_connection_get_setting_bridge (NMConnection *connection) NMSettingCdma * nm_connection_get_setting_cdma (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_CDMA); } /** @@ -2103,9 +2233,7 @@ nm_connection_get_setting_cdma (NMConnection *connection) NMSettingConnection * nm_connection_get_setting_connection (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_CONNECTION); } /** @@ -2119,9 +2247,7 @@ nm_connection_get_setting_connection (NMConnection *connection) NMSettingDcb * nm_connection_get_setting_dcb (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_DCB); } /** @@ -2137,9 +2263,7 @@ nm_connection_get_setting_dcb (NMConnection *connection) NMSettingDummy * nm_connection_get_setting_dummy (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingDummy *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DUMMY); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_DUMMY); } /** @@ -2153,9 +2277,7 @@ nm_connection_get_setting_dummy (NMConnection *connection) NMSettingGeneric * nm_connection_get_setting_generic (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingGeneric *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GENERIC); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_GENERIC); } /** @@ -2169,9 +2291,7 @@ nm_connection_get_setting_generic (NMConnection *connection) NMSettingGsm * nm_connection_get_setting_gsm (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_GSM); } /** @@ -2185,9 +2305,7 @@ nm_connection_get_setting_gsm (NMConnection *connection) NMSettingInfiniband * nm_connection_get_setting_infiniband (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_INFINIBAND); } /** @@ -2206,9 +2324,7 @@ nm_connection_get_setting_infiniband (NMConnection *connection) NMSettingIPConfig * nm_connection_get_setting_ip4_config (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP4_CONFIG); } /** @@ -2224,9 +2340,7 @@ nm_connection_get_setting_ip4_config (NMConnection *connection) NMSettingIPTunnel * nm_connection_get_setting_ip_tunnel (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingIPTunnel *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP_TUNNEL); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP_TUNNEL); } /** @@ -2245,9 +2359,7 @@ nm_connection_get_setting_ip_tunnel (NMConnection *connection) NMSettingIPConfig * nm_connection_get_setting_ip6_config (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_IP6_CONFIG); } /** @@ -2263,9 +2375,7 @@ nm_connection_get_setting_ip6_config (NMConnection *connection) NMSettingMacsec * nm_connection_get_setting_macsec (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingMacsec *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACSEC); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_MACSEC); } /** @@ -2281,9 +2391,7 @@ nm_connection_get_setting_macsec (NMConnection *connection) NMSettingMacvlan * nm_connection_get_setting_macvlan (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingMacvlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACVLAN); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_MACVLAN); } /** @@ -2297,9 +2405,71 @@ nm_connection_get_setting_macvlan (NMConnection *connection) NMSettingOlpcMesh * nm_connection_get_setting_olpc_mesh (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_OLPC_MESH); +} - return (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH); +/** + * nm_connection_get_setting_ovs_bridge: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsBridge the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsBridge if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsBridge * +nm_connection_get_setting_ovs_bridge (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_BRIDGE); +} + +/** + * nm_connection_get_setting_ovs_interface: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsInterface the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsInterface if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsInterface * +nm_connection_get_setting_ovs_interface (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_INTERFACE); +} + +/** + * nm_connection_get_setting_ovs_patch: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsPatch the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsPatch if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsPatch * +nm_connection_get_setting_ovs_patch (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_PATCH); +} + +/** + * nm_connection_get_setting_ovs_port: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingOvsPort the connection might contain. + * + * Returns: (transfer none): an #NMSettingOvsPort if the connection contains one, otherwise %NULL + * + * Since: 1.10 + **/ +NMSettingOvsPort * +nm_connection_get_setting_ovs_port (NMConnection *connection) +{ + return _connection_get_setting_check (connection, NM_TYPE_SETTING_OVS_PORT); } /** @@ -2313,9 +2483,7 @@ nm_connection_get_setting_olpc_mesh (NMConnection *connection) NMSettingPpp * nm_connection_get_setting_ppp (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingPpp *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_PPP); } /** @@ -2329,9 +2497,7 @@ nm_connection_get_setting_ppp (NMConnection *connection) NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingPppoe *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_PPPOE); } /** @@ -2347,9 +2513,7 @@ nm_connection_get_setting_pppoe (NMConnection *connection) NMSettingProxy * nm_connection_get_setting_proxy (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingProxy *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PROXY); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_PROXY); } /** @@ -2363,9 +2527,7 @@ nm_connection_get_setting_proxy (NMConnection *connection) NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_SERIAL); } /** @@ -2381,9 +2543,7 @@ nm_connection_get_setting_serial (NMConnection *connection) NMSettingTun * nm_connection_get_setting_tun (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingTun *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TUN); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_TUN); } /** @@ -2397,9 +2557,7 @@ nm_connection_get_setting_tun (NMConnection *connection) NMSettingVpn * nm_connection_get_setting_vpn (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingVpn *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_VPN); } /** @@ -2415,9 +2573,7 @@ nm_connection_get_setting_vpn (NMConnection *connection) NMSettingVxlan * nm_connection_get_setting_vxlan (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingVxlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VXLAN); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_VXLAN); } /** @@ -2431,9 +2587,7 @@ nm_connection_get_setting_vxlan (NMConnection *connection) NMSettingWimax * nm_connection_get_setting_wimax (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIMAX); } /** @@ -2447,9 +2601,7 @@ nm_connection_get_setting_wimax (NMConnection *connection) NMSettingWired * nm_connection_get_setting_wired (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRED); } /** @@ -2463,9 +2615,7 @@ nm_connection_get_setting_wired (NMConnection *connection) NMSettingAdsl * nm_connection_get_setting_adsl (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_ADSL); } /** @@ -2479,9 +2629,7 @@ nm_connection_get_setting_adsl (NMConnection *connection) NMSettingWireless * nm_connection_get_setting_wireless (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRELESS); } /** @@ -2495,9 +2643,7 @@ nm_connection_get_setting_wireless (NMConnection *connection) NMSettingWirelessSecurity * nm_connection_get_setting_wireless_security (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); } /** @@ -2511,9 +2657,7 @@ nm_connection_get_setting_wireless_security (NMConnection *connection) NMSettingBridgePort * nm_connection_get_setting_bridge_port (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - return (NMSettingBridgePort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE_PORT); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_BRIDGE_PORT); } /** @@ -2527,9 +2671,18 @@ nm_connection_get_setting_bridge_port (NMConnection *connection) NMSettingVlan * nm_connection_get_setting_vlan (NMConnection *connection) { - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + return _connection_get_setting_check (connection, NM_TYPE_SETTING_VLAN); +} + +NMSettingBluetooth * +_nm_connection_get_setting_bluetooth_for_nap (NMConnection *connection) +{ + NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (connection); - return (NMSettingVlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VLAN); + if ( s_bt + && nm_streq0 (nm_setting_bluetooth_get_connection_type (s_bt), NM_SETTING_BLUETOOTH_TYPE_NAP)) + return s_bt; + return NULL; } /*****************************************************************************/ @@ -2557,7 +2710,7 @@ nm_connection_get_private (NMConnection *connection) key = NM_CACHED_QUARK ("NMConnectionPrivate"); priv = g_object_get_qdata ((GObject *) connection, key); - if (!priv) { + if (G_UNLIKELY (!priv)) { priv = g_slice_new0 (NMConnectionPrivate); g_object_set_qdata_full ((GObject *) connection, key, priv, (GDestroyNotify) nm_connection_private_free); diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index fae9862a..c6b23a00 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -179,6 +179,10 @@ void nm_connection_for_each_setting_value (NMConnection *connection, NMSettingValueIterFn func, gpointer user_data); +NM_AVAILABLE_IN_1_10 +NMSetting ** nm_connection_get_settings (NMConnection *connection, + guint *out_length); + void nm_connection_dump (NMConnection *connection); /* Helpers */ @@ -213,6 +217,13 @@ NMSettingMacsec * nm_connection_get_setting_macsec (NMConnec NM_AVAILABLE_IN_1_2 NMSettingMacvlan * nm_connection_get_setting_macvlan (NMConnection *connection); NMSettingOlpcMesh * nm_connection_get_setting_olpc_mesh (NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsBridge * nm_connection_get_setting_ovs_bridge (NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsInterface * nm_connection_get_setting_ovs_interface (NMConnection *connection); +NMSettingOvsPatch * nm_connection_get_setting_ovs_patch (NMConnection *connection); +NM_AVAILABLE_IN_1_10 +NMSettingOvsPort * nm_connection_get_setting_ovs_port (NMConnection *connection); NMSettingPpp * nm_connection_get_setting_ppp (NMConnection *connection); NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnection *connection); NM_AVAILABLE_IN_1_6 diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 91967ce3..59ebfcb1 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -56,6 +56,10 @@ #include "nm-setting-macsec.h" #include "nm-setting-macvlan.h" #include "nm-setting-olpc-mesh.h" +#include "nm-setting-ovs-bridge.h" +#include "nm-setting-ovs-interface.h" +#include "nm-setting-ovs-patch.h" +#include "nm-setting-ovs-port.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-serial.h" @@ -142,7 +146,46 @@ NMConnection *_nm_simple_connection_new_from_dbus (GVariant *dict, NMSettingParseFlags parse_flags, GError **error); -guint32 _nm_setting_get_setting_priority (NMSetting *setting); +/* + * A setting's priority should roughly follow the OSI layer model, but it also + * controls which settings get asked for secrets first. Thus settings which + * relate to things that must be working first, like hardware, should get a + * higher priority than things which layer on top of the hardware. For example, + * the GSM/CDMA settings should provide secrets before the PPP setting does, + * because a PIN is required to unlock the device before PPP can even start. + * Even settings without secrets should be assigned the right priority. + * + * 0: reserved for invalid + * + * 1: reserved for the Connection setting + * + * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. + * These priority 1 settings are also "base types", which means that at least + * one of them is required for the connection to be valid, and their name is + * valid in the 'type' property of the Connection setting. + * + * 4: hardware-related auxiliary settings that require a base setting to be + * successful first, like Wi-Fi security, 802.1x, etc. + * + * 5: hardware-independent settings that are required before IP connectivity + * can be established, like PPP, PPPoE, etc. + * + * 6: IP-level stuff + * + * 10: NMSettingUser + */ +typedef enum { /*< skip >*/ + NM_SETTING_PRIORITY_INVALID = 0, + NM_SETTING_PRIORITY_CONNECTION = 1, + NM_SETTING_PRIORITY_HW_BASE = 2, + NM_SETTING_PRIORITY_HW_NON_BASE = 3, + NM_SETTING_PRIORITY_HW_AUX = 4, + NM_SETTING_PRIORITY_AUX = 5, + NM_SETTING_PRIORITY_IP = 6, + NM_SETTING_PRIORITY_USER = 10, +} NMSettingPriority; + +NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting); gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); @@ -159,6 +202,18 @@ GHashTable *_nm_utils_copy_strdict (GHashTable *strdict); typedef gpointer (*NMUtilsCopyFunc) (gpointer); +gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route); +const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length); +GHashTable *_nm_ip_route_get_attributes_direct (NMIPRoute *route); + +static inline void +_nm_auto_ip_route_unref (NMIPRoute **v) +{ + if (*v) + nm_ip_route_unref (*v); +} +#define nm_auto_ip_route_unref nm_auto (_nm_auto_ip_route_unref) + GPtrArray *_nm_utils_copy_slist_to_array (const GSList *list, NMUtilsCopyFunc copy_func, GDestroyNotify unref_func); @@ -175,11 +230,6 @@ gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpoi gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data); -char **_nm_utils_strv_cleanup (char **strv, - gboolean strip_whitespace, - gboolean skip_empty, - gboolean skip_repeated); - char ** _nm_utils_strsplit_set (const char *str, const char *delimiters, int max_tokens); @@ -204,14 +254,12 @@ gboolean _nm_utils_check_module_file (const char *name, gpointer user_data, GError **error); -char *_nm_utils_enum_to_str_full (GType type, int value, const char *sep); - #define NM_UTILS_UUID_TYPE_LEGACY 0 #define NM_UTILS_UUID_TYPE_VARIANT3 1 char *nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args); -/* arbitrarily choosen namespace UUID for _nm_utils_uuid_generate_from_strings() */ +/* arbitrarily chosen namespace UUID for _nm_utils_uuid_generate_from_strings() */ #define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905" char *_nm_utils_uuid_generate_from_strings (const char *string1, ...) G_GNUC_NULL_TERMINATED; @@ -294,7 +342,7 @@ extern const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[]; gboolean _nm_utils_dns_option_validate (const char *option, char **out_name, long *out_value, gboolean ipv6, const NMUtilsDNSOptionDesc *option_descs); -int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option); +gssize _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option); /*****************************************************************************/ @@ -377,6 +425,10 @@ gboolean _nm_setting_bond_option_supported (const char *option, NMBondMode mode) /*****************************************************************************/ +NMSettingBluetooth *_nm_connection_get_setting_bluetooth_for_nap (NMConnection *connection); + +/*****************************************************************************/ + gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr); /*****************************************************************************/ @@ -385,4 +437,16 @@ gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, g /*****************************************************************************/ +static inline int +nm_setting_ip_config_get_addr_family (NMSettingIPConfig *s_ip) +{ + if (NM_IS_SETTING_IP4_CONFIG (s_ip)) + return AF_INET; + if (NM_IS_SETTING_IP6_CONFIG (s_ip)) + return AF_INET6; + g_return_val_if_reached (AF_UNSPEC); +} + +/*****************************************************************************/ + #endif diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 3b9ec37b..ae680b7a 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -50,6 +50,10 @@ typedef struct _NMSettingIP6Config NMSettingIP6Config; typedef struct _NMSettingMacsec NMSettingMacsec; typedef struct _NMSettingMacvlan NMSettingMacvlan; typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh; +typedef struct _NMSettingOvsBridge NMSettingOvsBridge; +typedef struct _NMSettingOvsInterface NMSettingOvsInterface; +typedef struct _NMSettingOvsPatch NMSettingOvsPatch; +typedef struct _NMSettingOvsPort NMSettingOvsPort; typedef struct _NMSettingPpp NMSettingPpp; typedef struct _NMSettingPppoe NMSettingPppoe; typedef struct _NMSettingSerial NMSettingSerial; diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 4c8e46fc..7f75c849 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2004 - 2014 Red Hat, Inc. + * Copyright 2004 - 2017 Red Hat, Inc. */ /* Definitions related to NetworkManager's D-Bus interfaces. @@ -36,42 +36,46 @@ /* * dbus services details */ -#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" - -#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" -#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" -#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device" -#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" -#define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" -#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" -#define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" -#define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" -#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" -#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" -#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" -#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" -#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" -#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" -#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" -#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" -#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" -#define NM_DBUS_INTERFACE_IP6_CONFIG NM_DBUS_INTERFACE ".IP6Config" -#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config" -#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband" -#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond" -#define NM_DBUS_INTERFACE_DEVICE_DUMMY NM_DBUS_INTERFACE_DEVICE ".Dummy" -#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team" -#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" -#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge" -#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic" -#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth" -#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun" -#define NM_DBUS_INTERFACE_DEVICE_MACSEC NM_DBUS_INTERFACE_DEVICE ".Macsec" -#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" -#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" -#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" -#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" -#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" +#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" + +#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" +#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device" +#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" +#define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" +#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" +#define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" +#define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" +#define NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE NM_DBUS_INTERFACE_DEVICE ".OvsInterface" +#define NM_DBUS_INTERFACE_DEVICE_OVS_PORT NM_DBUS_INTERFACE_DEVICE ".OvsPort" +#define NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE NM_DBUS_INTERFACE_DEVICE ".OvsBridge" +#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" +#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" +#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" +#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" +#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" +#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" +#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" +#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" +#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" +#define NM_DBUS_INTERFACE_IP6_CONFIG NM_DBUS_INTERFACE ".IP6Config" +#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config" +#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband" +#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond" +#define NM_DBUS_INTERFACE_DEVICE_DUMMY NM_DBUS_INTERFACE_DEVICE ".Dummy" +#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team" +#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan" +#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge" +#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic" +#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth" +#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun" +#define NM_DBUS_INTERFACE_DEVICE_MACSEC NM_DBUS_INTERFACE_DEVICE ".Macsec" +#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" +#define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp" +#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" +#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre" +#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel" +#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics" #define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings" #define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings" @@ -203,34 +207,42 @@ typedef enum { * @NM_DEVICE_TYPE_VETH: a VETH interface * @NM_DEVICE_TYPE_MACSEC: a MACsec interface * @NM_DEVICE_TYPE_DUMMY: a dummy interface + * @NM_DEVICE_TYPE_PPP: a PPP interface + * @NM_DEVICE_TYPE_OVS_INTERFACE: a OpenVSwitch interface + * @NM_DEVICE_TYPE_OVS_PORT: a OpenVSwitch port + * @NM_DEVICE_TYPE_OVS_BRIDGE: a OpenVSwitch bridge * * #NMDeviceType values indicate the type of hardware represented by a * device object. **/ typedef enum { - NM_DEVICE_TYPE_UNKNOWN = 0, - NM_DEVICE_TYPE_ETHERNET = 1, - NM_DEVICE_TYPE_WIFI = 2, - NM_DEVICE_TYPE_UNUSED1 = 3, - NM_DEVICE_TYPE_UNUSED2 = 4, - NM_DEVICE_TYPE_BT = 5, /* Bluetooth */ - NM_DEVICE_TYPE_OLPC_MESH = 6, - NM_DEVICE_TYPE_WIMAX = 7, - NM_DEVICE_TYPE_MODEM = 8, - NM_DEVICE_TYPE_INFINIBAND = 9, - NM_DEVICE_TYPE_BOND = 10, - NM_DEVICE_TYPE_VLAN = 11, - NM_DEVICE_TYPE_ADSL = 12, - NM_DEVICE_TYPE_BRIDGE = 13, - NM_DEVICE_TYPE_GENERIC = 14, - NM_DEVICE_TYPE_TEAM = 15, - NM_DEVICE_TYPE_TUN = 16, - NM_DEVICE_TYPE_IP_TUNNEL = 17, - NM_DEVICE_TYPE_MACVLAN = 18, - NM_DEVICE_TYPE_VXLAN = 19, - NM_DEVICE_TYPE_VETH = 20, - NM_DEVICE_TYPE_MACSEC = 21, - NM_DEVICE_TYPE_DUMMY = 22, + NM_DEVICE_TYPE_UNKNOWN = 0, + NM_DEVICE_TYPE_ETHERNET = 1, + NM_DEVICE_TYPE_WIFI = 2, + NM_DEVICE_TYPE_UNUSED1 = 3, + NM_DEVICE_TYPE_UNUSED2 = 4, + NM_DEVICE_TYPE_BT = 5, /* Bluetooth */ + NM_DEVICE_TYPE_OLPC_MESH = 6, + NM_DEVICE_TYPE_WIMAX = 7, + NM_DEVICE_TYPE_MODEM = 8, + NM_DEVICE_TYPE_INFINIBAND = 9, + NM_DEVICE_TYPE_BOND = 10, + NM_DEVICE_TYPE_VLAN = 11, + NM_DEVICE_TYPE_ADSL = 12, + NM_DEVICE_TYPE_BRIDGE = 13, + NM_DEVICE_TYPE_GENERIC = 14, + NM_DEVICE_TYPE_TEAM = 15, + NM_DEVICE_TYPE_TUN = 16, + NM_DEVICE_TYPE_IP_TUNNEL = 17, + NM_DEVICE_TYPE_MACVLAN = 18, + NM_DEVICE_TYPE_VXLAN = 19, + NM_DEVICE_TYPE_VETH = 20, + NM_DEVICE_TYPE_MACSEC = 21, + NM_DEVICE_TYPE_DUMMY = 22, + NM_DEVICE_TYPE_PPP = 23, + NM_DEVICE_TYPE_OVS_INTERFACE = 24, + NM_DEVICE_TYPE_OVS_PORT = 25, + NM_DEVICE_TYPE_OVS_BRIDGE = 26, } NMDeviceType; /** @@ -289,12 +301,18 @@ typedef enum { /*< flags >*/ * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities * @NM_802_11_AP_FLAGS_PRIVACY: access point requires authentication and * encryption (usually means WEP) + * @NM_802_11_AP_FLAGS_WPS: access point supports some WPS method + * @NM_802_11_AP_FLAGS_WPS_PBC: access point supports push-button WPS + * @NM_802_11_AP_FLAGS_WPS_PIN: access point supports PIN-based WPS * * 802.11 access point flags. **/ typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/ NM_802_11_AP_FLAGS_NONE = 0x00000000, NM_802_11_AP_FLAGS_PRIVACY = 0x00000001, + NM_802_11_AP_FLAGS_WPS = 0x00000002, + NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004, + NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008, } NM80211ApFlags; /** @@ -532,6 +550,7 @@ typedef enum { * @NM_DEVICE_STATE_REASON_NEW_ACTIVATION: New connection activation was enqueued * @NM_DEVICE_STATE_REASON_PARENT_CHANGED: the device's parent changed * @NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED: the device parent's management changed + * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with OpenVSwitch database * * Device state change reason codes */ @@ -599,6 +618,7 @@ typedef enum { NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60, NM_DEVICE_STATE_REASON_PARENT_CHANGED = 61, NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62, + NM_DEVICE_STATE_REASON_OVSDB_FAILED = 63, } NMDeviceStateReason; /** @@ -714,6 +734,9 @@ typedef enum { * initiated by user-requested action via the D-Bus interface, as opposed to * automatically initiated by NetworkManager in response to (for example) scan * results or carrier changes. + * @NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE: indicates that WPS enrollment + * is active with PBC method. The agent may suggest that the user pushes a button + * on the router instead of supplying a PSK. * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM: Internal flag, not part of * the D-Bus API. * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of @@ -726,6 +749,7 @@ typedef enum { /*< flags >*/ NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1, NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2, NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4, + NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE = 0x8, /* Internal to NM; not part of the D-Bus API */ NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000, @@ -843,4 +867,30 @@ typedef enum { /*< skip >*/ NM_ROLLBACK_RESULT_ERR_FAILED = 3, } NMRollbackResult; +/** + * NMActivationStateFlags: + * @NM_ACTIVATION_STATE_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_ACTIVATION_STATE_FLAG_IS_MASTER: the device is a master. + * @NM_ACTIVATION_STATE_FLAG_IS_SLAVE: the device is a slave. + * @NM_ACTIVATION_STATE_FLAG_LAYER2_READY: layer2 is activated and ready. + * @NM_ACTIVATION_STATE_FLAG_IP4_READY: IPv4 setting is completed. + * @NM_ACTIVATION_STATE_FLAG_IP6_READY: IPv6 setting is completed. + * @NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES: The master has any slave devices attached. + * This only makes sense if the device is a master. + * + * Flags describing the current activation state. + * + * Since: 1.10 + **/ +typedef enum { /*< flags >*/ + NM_ACTIVATION_STATE_FLAG_NONE = 0, + + NM_ACTIVATION_STATE_FLAG_IS_MASTER = (1LL << 0), + NM_ACTIVATION_STATE_FLAG_IS_SLAVE = (1LL << 1), + NM_ACTIVATION_STATE_FLAG_LAYER2_READY = (1LL << 2), + NM_ACTIVATION_STATE_FLAG_IP4_READY = (1LL << 3), + NM_ACTIVATION_STATE_FLAG_IP6_READY = (1LL << 4), + NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES = (1LL << 5), +} NMActivationStateFlags; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml index c9d5d74d..ba58a615 100644 --- a/libnm-core/nm-dbus-types.xml +++ b/libnm-core/nm-dbus-types.xml @@ -272,6 +272,26 @@ <entry role="enum_member_value"><para>= <literal>22</literal></para><para></para></entry> <entry role="enum_member_description"><para>a dummy interface</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_PPP</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>23</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a PPP interface</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_OVS_INTERFACE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>24</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a OpenVSwitch interface</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_OVS_PORT</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>25</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a OpenVSwitch port</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_TYPE_OVS_BRIDGE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>26</literal></para><para></para></entry> + <entry role="enum_member_description"><para>a OpenVSwitch bridge</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -427,6 +447,21 @@ <entry role="enum_member_value"><para>= <literal>0x00000001</literal></para><para></para></entry> <entry role="enum_member_description"><para>access point requires authentication and encryption (usually means WEP)</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_802_11_AP_FLAGS_WPS</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x00000002</literal></para><para></para></entry> + <entry role="enum_member_description"><para>access point supports some WPS method</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_802_11_AP_FLAGS_WPS_PBC</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x00000004</literal></para><para></para></entry> + <entry role="enum_member_description"><para>access point supports push-button WPS</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_802_11_AP_FLAGS_WPS_PIN</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x00000008</literal></para><para></para></entry> + <entry role="enum_member_description"><para>access point supports PIN-based WPS</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1082,6 +1117,11 @@ <entry role="enum_member_value"><para>= <literal>62</literal></para><para></para></entry> <entry role="enum_member_description"><para>the device parent's management changed</para><para></para></entry> </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_OVSDB_FAILED</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>63</literal></para><para></para></entry> + <entry role="enum_member_description"><para>problem communicating with OpenVSwitch database</para><para></para></entry> + </row> </tbody> </tgroup> </informaltable> @@ -1308,6 +1348,11 @@ <entry role="enum_member_description"><para>set if the request was initiated by user-requested action via the D-Bus interface, as opposed to automatically initiated by NetworkManager in response to (for example) scan results or carrier changes.</para><para></para></entry> </row> <row role="constant"> + <entry role="enum_member_name"><para>NM_SECRET_AGENT_GET_SECRETS_FLAG_WPS_PBC_ACTIVE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0x8</literal></para><para></para></entry> + <entry role="enum_member_description"><para>indicates that WPS enrollment is active with PBC method. The agent may suggest that the user pushes a button on the router instead of supplying a PSK.</para><para></para></entry> + </row> + <row role="constant"> <entry role="enum_member_name"><para>NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM</para><para></para></entry> <entry role="enum_member_value"><para>= <literal>0x80000000</literal></para><para></para></entry> <entry role="enum_member_description"><para>Internal flag, not part of the D-Bus API.</para><para></para></entry> @@ -1503,4 +1548,59 @@ </refsect3> </refsect2> + <refsect2 id="NMActivationStateFlags" role="enum"> + <title>enum NMActivationStateFlags</title> + <indexterm zone="NMActivationStateFlags"> + <primary>NMActivationStateFlags</primary> + </indexterm> + <para><para>Flags describing the current activation state.</para><para>Since: 1.10</para><para></para></para> + <refsect3 role="enum_members"> + <title>Values</title> + <informaltable role="enum_members_table" pgwide="1" frame="none"> + <tgroup cols="4"> + <colspec colname="enum_members_name" colwidth="300px" /> + <colspec colname="enum_members_value" colwidth="100px"/> + <colspec colname="enum_members_description" /> + <tbody> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_NONE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry> + <entry role="enum_member_description"><para>an alias for numeric zero, no flags set.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_IS_MASTER</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the device is a master.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_IS_SLAVE</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>the device is a slave.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_LAYER2_READY</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>layer2 is activated and ready.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_IP4_READY</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>IPv4 setting is completed.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_IP6_READY</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>IPv6 setting is completed.</para><para></para></entry> + </row> + <row role="constant"> + <entry role="enum_member_name"><para>NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES</para><para></para></entry> + <entry role="enum_member_value"><para>= <literal>(1LL</literal></para><para></para></entry> + <entry role="enum_member_description"><para>The master has any slave devices attached. This only makes sense if the device is a master.</para><para></para></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect3> + </refsect2> + </refentry> diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h index 35f7dc2f..6bacc8da 100644 --- a/libnm-core/nm-errors.h +++ b/libnm-core/nm-errors.h @@ -143,6 +143,8 @@ GQuark nm_crypto_error_quark (void); * activation request (eg, the #NMAccessPoint or #NMWimaxNsp) was not * found. * @NM_DEVICE_ERROR_VERSION_ID_MISMATCH: the version id did not match. + * @NM_DEVICE_ERROR_MISSING_DEPENDENCIES: the requested operation could not + * be completed due to missing dependencies. * * Device-related errors. * @@ -160,6 +162,7 @@ typedef enum { NM_DEVICE_ERROR_NOT_ALLOWED, /*< nick=NotAllowed >*/ NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, /*< nick=SpecificObjectNotFound >*/ NM_DEVICE_ERROR_VERSION_ID_MISMATCH, /*< nick=VersionIdMismatch >*/ + NM_DEVICE_ERROR_MISSING_DEPENDENCIES, /*< nick=MissingDependencies >*/ } NMDeviceError; #define NM_DEVICE_ERROR nm_device_error_quark () diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h index be11a708..5b709c02 100644 --- a/libnm-core/nm-keyfile-internal.h +++ b/libnm-core/nm-keyfile-internal.h @@ -28,7 +28,7 @@ #include "nm-setting-8021x.h" #include "nm-core-internal.h" -#include "nm-setting-metadata.h" +#include "nm-meta-setting.h" /*****************************************************************************/ diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c index eb257eeb..0ac417cd 100644 --- a/libnm-core/nm-keyfile-reader.c +++ b/libnm-core/nm-keyfile-reader.c @@ -133,8 +133,7 @@ read_array_of_uint (GKeyFile *file, static gboolean get_one_int (KeyfileReaderInfo *info, const char *property_name, const char *str, guint32 max_val, guint32 *out) { - long tmp; - char *endptr; + gint64 tmp; g_return_val_if_fail (!info == !property_name, FALSE); @@ -145,13 +144,13 @@ get_one_int (KeyfileReaderInfo *info, const char *property_name, const char *str return FALSE; } - errno = 0; - tmp = strtol (str, &endptr, 10); - if (errno || (tmp < 0) || (tmp > max_val) || *endptr != 0) { - if (property_name) + tmp = _nm_utils_ascii_str_to_int64 (str, 10, 0, max_val, -1); + if (tmp == -1) { + if (property_name) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid number '%s'"), str); + } return FALSE; } @@ -186,7 +185,8 @@ build_route (KeyfileReaderInfo *info, const char *gateway_str, const char *metric_str) { NMIPRoute *route; - guint32 metric = 0; + guint32 u32; + gint64 metric = -1; GError *error = NULL; g_return_val_if_fail (plen, NULL); @@ -205,9 +205,10 @@ build_route (KeyfileReaderInfo *info, **/ if ( family == AF_INET6 && !metric_str - && get_one_int (NULL, NULL, gateway_str, G_MAXUINT32, &metric)) + && get_one_int (NULL, NULL, gateway_str, G_MAXUINT32, &u32)) { + metric = u32; gateway_str = NULL; - else { + } else { if (!info->error) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, _("ignoring invalid gateway '%s' for %s route"), @@ -219,14 +220,15 @@ build_route (KeyfileReaderInfo *info, } else gateway_str = NULL; - /* parse metric, default to 0 */ + /* parse metric, default to -1 */ if (metric_str) { - if (!get_one_int (info, property_name, metric_str, G_MAXUINT32, &metric)) + if (!get_one_int (info, property_name, metric_str, G_MAXUINT32, &u32)) return NULL; + metric = u32; } route = nm_ip_route_new (family, dest_str, plen, gateway_str, - metric ? (gint64) metric : -1, + metric, &error); if (!route) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, @@ -250,17 +252,17 @@ build_route (KeyfileReaderInfo *info, * When @current target is %NULL, gracefully fail returning %NULL while * leaving the @current target %NULL end setting @error to %NULL; */ -static char * -read_field (char **current, char **error, const char *characters, const char *delimiters) +static const char * +read_field (char **current, const char **out_err_str, const char *characters, const char *delimiters) { - char *start; + const char *start; - g_return_val_if_fail (current, NULL); - g_return_val_if_fail (error, NULL); - g_return_val_if_fail (characters, NULL); - g_return_val_if_fail (delimiters, NULL); + nm_assert (current); + nm_assert (out_err_str); + nm_assert (characters); + nm_assert (delimiters); - *error = NULL; + *out_err_str = NULL; if (!*current) { /* graceful failure, leave '*current' NULL */ @@ -283,8 +285,8 @@ read_field (char **current, char **error, const char *characters, const char *de return start; } else { /* error, bad character */ - *error = *current; - *current = start; + *out_err_str = *current; + *current = (char *) start; return NULL; } else { @@ -333,42 +335,50 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info, char **out_gateway, NMSetting *setting) { - guint32 plen = G_MAXUINT32; + guint plen; gpointer result; - char *address_str, *plen_str, *gateway_str, *metric_str, *current, *error; - gs_free char *value = NULL, *value_orig = NULL; + const char *address_str; + const char *plen_str; + const char *gateway_str; + const char *metric_str; + const char *err_str = NULL; + char *current; + gs_free char *value = NULL; + gs_free char *value_orig = NULL; #define VALUE_ORIG() (value_orig ? value_orig : (value_orig = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL))) - current = value = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL); + value = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key_name, NULL); if (!value) return NULL; + current = value; + /* get address field */ - address_str = read_field (¤t, &error, IP_ADDRESS_CHARS, DELIMITERS); - if (error) { + address_str = read_field (¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); + if (err_str) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, _("unexpected character '%c' for address %s: '%s' (position %td)"), - *error, key_name, VALUE_ORIG (), error - current); + *err_str, key_name, VALUE_ORIG (), err_str - current); return NULL; } /* get prefix length field (skippable) */ - plen_str = read_field (¤t, &error, DIGITS, DELIMITERS); + plen_str = read_field (¤t, &err_str, DIGITS, DELIMITERS); /* get gateway field */ - gateway_str = read_field (¤t, &error, IP_ADDRESS_CHARS, DELIMITERS); - if (error) { + gateway_str = read_field (¤t, &err_str, IP_ADDRESS_CHARS, DELIMITERS); + if (err_str) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, _("unexpected character '%c' for %s: '%s' (position %td)"), - *error, key_name, VALUE_ORIG (), error - current); + *err_str, key_name, VALUE_ORIG (), err_str - current); return NULL; } /* for routes, get metric */ if (route) { - metric_str = read_field (¤t, &error, DIGITS, DELIMITERS); - if (error) { + metric_str = read_field (¤t, &err_str, DIGITS, DELIMITERS); + if (err_str) { handle_warn (info, property_name, NM_KEYFILE_WARN_SEVERITY_WARN, _("unexpected character '%c' in prefix length for %s: '%s' (position %td)"), - *error, key_name, VALUE_ORIG (), error - current); + *err_str, key_name, VALUE_ORIG (), err_str - current); return NULL; } } else @@ -394,7 +404,7 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info, /* parse plen, fallback to defaults */ if (plen_str) { - if (!get_one_int (info, property_name, plen_str, ipv6 ? 128 : 32, &plen) + if ( !get_one_int (info, property_name, plen_str, ipv6 ? 128 : 32, &plen) || (route && plen == 0)) { plen = DEFAULT_PREFIX (route, ipv6); if ( info->error diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c index 6a3d9a9f..30d519c4 100644 --- a/libnm-core/nm-keyfile-writer.c +++ b/libnm-core/nm-keyfile-writer.c @@ -47,7 +47,7 @@ typedef struct { * NMSettingConnection's 'type' property (which specifies the base type of the * connection, eg ethernet or wifi) or the 802-11-wireless setting's * 'security' property which specifies whether or not the AP requires - * encrpytion. This function handles translating those properties' values + * encryption. This function handles translating those properties' values * from the real setting name to the more-readable alias. */ static void @@ -137,7 +137,7 @@ write_ip_values (GKeyFile *file, GString *output; int family, i; const char *addr, *gw; - guint32 plen, metric; + guint32 plen; char key_name[64], *key_name_idx; if (!array->len) @@ -150,25 +150,27 @@ write_ip_values (GKeyFile *file, output = g_string_sized_new (2*INET_ADDRSTRLEN + 10); for (i = 0; i < array->len; i++) { + gint64 metric = -1; + if (is_route) { NMIPRoute *route = array->pdata[i]; addr = nm_ip_route_get_dest (route); plen = nm_ip_route_get_prefix (route); gw = nm_ip_route_get_next_hop (route); - metric = MAX (0, nm_ip_route_get_metric (route)); + metric = nm_ip_route_get_metric (route); } else { NMIPAddress *address = array->pdata[i]; addr = nm_ip_address_get_address (address); plen = nm_ip_address_get_prefix (address); gw = i == 0 ? gateway : NULL; - metric = 0; } g_string_set_size (output, 0); g_string_append_printf (output, "%s/%u", addr, plen); - if (metric || gw) { + if ( metric != -1 + || gw) { /* Older versions of the plugin do not support the form * "a.b.c.d/plen,,metric", so, we always have to write the * gateway, even if there isn't one. @@ -182,7 +184,7 @@ write_ip_values (GKeyFile *file, } g_string_append_printf (output, ",%s", gw); - if (metric) + if (is_route && metric != -1) g_string_append_printf (output, ",%lu", (unsigned long) metric); } @@ -191,14 +193,9 @@ write_ip_values (GKeyFile *file, if (is_route) { gs_free char *attributes = NULL; - gs_strfreev char **names = NULL; - gs_unref_hashtable GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); - int j; - - names = nm_ip_route_get_attribute_names (array->pdata[i]); - for (j = 0; names && names[j]; j++) - g_hash_table_insert (hash, names[j], nm_ip_route_get_attribute (array->pdata[i], names[j])); + GHashTable *hash; + hash = _nm_ip_route_get_attributes_direct (array->pdata[i]); attributes = nm_utils_format_variant_attributes (hash, ',', '='); if (attributes) { g_strlcat (key_name, "_options", sizeof (key_name)); diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c index ab0f5c66..af195211 100644 --- a/libnm-core/nm-setting-8021x.c +++ b/libnm-core/nm-setting-8021x.c @@ -61,7 +61,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING, - _nm_register_setting (802_1X, 2)) + _nm_register_setting (802_1X, NM_SETTING_PRIORITY_HW_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_802_1X) #define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate)) @@ -2772,6 +2772,7 @@ need_secrets_sim (NMSetting8021x *self, static gboolean need_private_key_password (GBytes *blob, + NMSetting8021xCKScheme scheme, const char *path, const char *password, NMSettingSecretFlags flags) @@ -2781,6 +2782,10 @@ need_private_key_password (GBytes *blob, if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) return FALSE; + if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 + && flags == NM_SETTING_SECRET_FLAG_NONE) + return FALSE; + /* Private key password is required */ if (password) { if (path) @@ -2815,20 +2820,22 @@ need_secrets_tls (NMSetting8021x *self, else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) g_warning ("%s: unknown phase2 private key scheme %d", __func__, scheme); - if (need_private_key_password (blob, path, + if (need_private_key_password (blob, scheme, path, priv->phase2_private_key_password, priv->phase2_private_key_password_flags)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD); scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (self); if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->phase2_ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !( priv->phase2_ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE + || priv->phase2_ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) && !priv->phase2_ca_cert_password) g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD); scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (self); if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->phase2_client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !( priv->phase2_client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || priv->phase2_client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) && !priv->phase2_client_cert_password) g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD); } else { @@ -2840,20 +2847,22 @@ need_secrets_tls (NMSetting8021x *self, else if (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) g_warning ("%s: unknown private key scheme %d", __func__, scheme); - if (need_private_key_password (blob, path, + if (need_private_key_password (blob, scheme, path, priv->private_key_password, priv->private_key_password_flags)) g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); scheme = nm_setting_802_1x_get_ca_cert_scheme (self); if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !( priv->ca_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || priv->ca_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE) && !priv->ca_cert_password) g_ptr_array_add (secrets, NM_SETTING_802_1X_CA_CERT_PASSWORD); scheme = nm_setting_802_1x_get_client_cert_scheme (self); if ( scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11 - && !(priv->client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + && !( priv->client_cert_password_flags == NM_SETTING_SECRET_FLAG_NONE + || priv->client_cert_password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) && !priv->client_cert_password) g_ptr_array_add (secrets, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); } @@ -4170,7 +4179,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) * * Specifies authentication flags to use in "phase 1" outer * authentication using #NMSetting8021xAuthFlags options. - * The invidual TLS versions can be explicitly disabled. If a certain + * The individual TLS versions can be explicitly disabled. If a certain * TLS disable flag is not set, it is up to the supplicant to allow * or forbid it. The TLS options map to tls_disable_tlsv1_x settings. * See the wpa_supplicant documentation for more details. @@ -4518,8 +4527,10 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) **/ /* ---ifcfg-rh--- * property: password-raw - * variable: (none) - * description: The property is not handled by ifcfg-rh plugin. + * variable: IEEE_8021X_PASSWORD_RAW(+) + * description: password used for EAP, encoded as a hexadecimal string. It + * can also go to "key-" lookaside file. + * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf * ---end--- */ g_object_class_install_property @@ -4813,5 +4824,4 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class) G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); - } diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c index 8198a72a..8be288b6 100644 --- a/libnm-core/nm-setting-adsl.c +++ b/libnm-core/nm-setting-adsl.c @@ -38,7 +38,7 @@ */ G_DEFINE_TYPE_WITH_CODE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING, - _nm_register_setting (ADSL, 1)) + _nm_register_setting (ADSL, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_ADSL) #define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate)) diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c index 837b06c0..5b6ef3eb 100644 --- a/libnm-core/nm-setting-bluetooth.c +++ b/libnm-core/nm-setting-bluetooth.c @@ -25,6 +25,7 @@ #include <string.h> #include <net/ethernet.h> +#include "nm-connection-private.h" #include "nm-setting-bluetooth.h" #include "nm-setting-cdma.h" #include "nm-setting-gsm.h" @@ -43,7 +44,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING, - _nm_register_setting (BLUETOOTH, 1)) + _nm_register_setting (BLUETOOTH, NM_SETTING_PRIORITY_HW_NON_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BLUETOOTH) #define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate)) @@ -80,8 +81,8 @@ NMSetting *nm_setting_bluetooth_new (void) * Returns the connection method for communicating with the remote device (i.e. * either DUN to a DUN-capable device or PANU to a NAP-capable device). * - * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU or - * %NM_SETTING_BLUETOOTH_TYPE_DUN + * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU, + * %NM_SETTING_BLUETOOTH_TYPE_NAP or %NM_SETTING_BLUETOOTH_TYPE_DUN **/ const char * nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting) @@ -112,17 +113,10 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (setting); + const char *type; + gboolean missing_nap_bridge = FALSE; - if (!priv->bdaddr) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR); - return FALSE; - } - - if (!nm_utils_hwaddr_valid (priv->bdaddr, ETH_ALEN)) { + if (priv->bdaddr && !nm_utils_hwaddr_valid (priv->bdaddr, ETH_ALEN)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -131,27 +125,38 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (!priv->type) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_MISSING_PROPERTY, - _("property is missing")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE); - return FALSE; - } else if (!g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN) && - !g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_PANU)) { + type = priv->type; + if (!type) { + if (connection) { + /* We may infer the type from the (non-)existence of gsm/cdma/bridge settings. */ + type = _nm_connection_detect_bluetooth_type (connection); + } + if (!type) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE); + return FALSE; + } + } + + if (!NM_IN_STRSET (type, NM_SETTING_BLUETOOTH_TYPE_DUN, + NM_SETTING_BLUETOOTH_TYPE_NAP, + NM_SETTING_BLUETOOTH_TYPE_PANU)) { + nm_assert (priv->type == type); g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid value for the property"), - priv->type); + type); g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE); return FALSE; } /* Make sure the corresponding 'type' setting is present */ if ( connection - && !strcmp (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN)) { + && nm_streq (type, NM_SETTING_BLUETOOTH_TYPE_DUN)) { gboolean gsm = FALSE, cdma = FALSE; gsm = !!nm_connection_get_setting_gsm (connection); @@ -176,6 +181,48 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) * is required at the interface level. */ + /* NAP mode needs a bridge setting, and a bridge needs a name. */ + if (nm_streq (type, NM_SETTING_BLUETOOTH_TYPE_NAP)) { + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + if ( connection + && !nm_connection_get_setting_bridge (connection)) + missing_nap_bridge = TRUE; + } else { + if (!priv->bdaddr) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR); + return FALSE; + } + } + + /* errors form here are normalizable. */ + + if (!priv->type) { + /* as determined above, we can detect the bluetooth type. */ + nm_assert (!missing_nap_bridge); + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + if (missing_nap_bridge) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("'%s' connection requires '%s' setting"), + NM_SETTING_BLUETOOTH_TYPE_NAP, + NM_SETTING_BRIDGE_SETTING_NAME); + g_prefix_error (error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + return TRUE; } diff --git a/libnm-core/nm-setting-bluetooth.h b/libnm-core/nm-setting-bluetooth.h index 312aab14..58326702 100644 --- a/libnm-core/nm-setting-bluetooth.h +++ b/libnm-core/nm-setting-bluetooth.h @@ -54,12 +54,20 @@ G_BEGIN_DECLS /** * NM_SETTING_BLUETOOTH_TYPE_PANU: * - * Connection type describing a connection to devices that support the Bluetooth - * NAP (Network Access Point) protocol, which accepts connections via PANU. + * Connection type describing PANU connection to a Bluetooth NAP (Network + * Access Point). */ #define NM_SETTING_BLUETOOTH_TYPE_PANU "panu" /** + * NM_SETTING_BLUETOOTH_TYPE_NAP: + * + * Connection type describing a Bluetooth NAP (Network Access Point), + * which accepts PANU clients. + */ +#define NM_SETTING_BLUETOOTH_TYPE_NAP "nap" + +/** * NMSettingBluetooth: * * Bluetooth Settings diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c index 165001b0..d12940f6 100644 --- a/libnm-core/nm-setting-bond.c +++ b/libnm-core/nm-setting-bond.c @@ -43,7 +43,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING, - _nm_register_setting (BOND, 1)) + _nm_register_setting (BOND, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BOND) #define NM_SETTING_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate)) @@ -224,19 +224,34 @@ validate_list (const char *name, const char *value, const BondDefault *def) static gboolean validate_ip (const char *name, const char *value) { - char **ips, **iter; - gboolean success = TRUE; + gs_free char *value_clone = NULL; struct in_addr addr; if (!value || !value[0]) return FALSE; - ips = g_strsplit_set (value, ",", 0); - for (iter = ips; iter && *iter && success; iter++) - success = !!inet_aton (*iter, &addr); - g_strfreev (ips); + value_clone = g_strdup (value); + value = value_clone; + for (;;) { + char *eow; - return success; + /* we do not skip over empty words. E.g + * "192.168.1.1," is an error. + * + * ... for no particular reason. */ + + eow = strchr (value, ','); + if (eow) + *eow = '\0'; + + if (inet_pton (AF_INET, value, &addr) != 1) + return FALSE; + + if (!eow) + break; + value = eow + 1; + } + return TRUE; } static gboolean @@ -627,7 +642,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("'%s' is not a valid for '%s' option: %s"), + _("'%s' is not valid for the '%s' option: %s"), primary, NM_SETTING_BOND_OPTION_PRIMARY, tmp_error->message); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); g_error_free (tmp_error); @@ -646,7 +661,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - if (nm_connection_get_setting_infiniband (connection)) { + if (connection && nm_connection_get_setting_infiniband (connection)) { if (strcmp (mode_new, "active-backup") != 0) { g_set_error (error, NM_CONNECTION_ERROR, diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c index 0116a836..3fc0e873 100644 --- a/libnm-core/nm-setting-bridge-port.c +++ b/libnm-core/nm-setting-bridge-port.c @@ -41,7 +41,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE_PORT, 3)) + _nm_register_setting (BRIDGE_PORT, NM_SETTING_PRIORITY_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE_PORT) #define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate)) @@ -273,7 +273,7 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class) /** * NMSettingBridgePort:hairpin-mode: * - * Enables or disabled "hairpin mode" for the port, which allows frames to + * Enables or disables "hairpin mode" for the port, which allows frames to * be sent back out through the port the frame was received on. **/ /* ---ifcfg-rh--- diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c index 7cfa7eb8..53300384 100644 --- a/libnm-core/nm-setting-bridge.c +++ b/libnm-core/nm-setting-bridge.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2011 - 2013 Red Hat, Inc. + * Copyright 2011 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -39,7 +39,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING, - _nm_register_setting (BRIDGE, 1)) + _nm_register_setting (BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE) #define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate)) @@ -52,6 +52,7 @@ typedef struct { guint16 hello_time; guint16 max_age; guint32 ageing_time; + guint16 group_forward_mask; gboolean multicast_snooping; } NMSettingBridgePrivate; @@ -64,6 +65,7 @@ enum { PROP_HELLO_TIME, PROP_MAX_AGE, PROP_AGEING_TIME, + PROP_GROUP_FORWARD_MASK, PROP_MULTICAST_SNOOPING, LAST_PROP }; @@ -180,6 +182,22 @@ nm_setting_bridge_get_ageing_time (NMSettingBridge *setting) } /** + * nm_setting_bridge_get_group_forward_mask: + * @setting: the #NMSettingBridge + * + * Returns: the #NMSettingBridge:group-forward-mask property of the setting + * + * Since: 1.10 + **/ +guint16 +nm_setting_bridge_get_group_forward_mask (NMSettingBridge *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0); + + return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->group_forward_mask; +} + +/** * nm_setting_bridge_get_multicast_snooping: * @setting: the #NMSettingBridge * @@ -278,6 +296,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) error)) return FALSE; + if (priv->group_forward_mask & 7) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the mask can't contain bits 0 (STP), 1 (MAC) or 2 (LACP)")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_GROUP_FORWARD_MASK); + return FALSE; + } + return _nm_connection_verify_required_interface_name (connection, error); } @@ -326,6 +353,9 @@ set_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: priv->ageing_time = g_value_get_uint (value); break; + case PROP_GROUP_FORWARD_MASK: + priv->group_forward_mask = (guint16) g_value_get_uint (value); + break; case PROP_MULTICAST_SNOOPING: priv->multicast_snooping = g_value_get_boolean (value); break; @@ -364,6 +394,9 @@ get_property (GObject *object, guint prop_id, case PROP_AGEING_TIME: g_value_set_uint (value, priv->ageing_time); break; + case PROP_GROUP_FORWARD_MASK: + g_value_set_uint (value, priv->group_forward_mask); + break; case PROP_MULTICAST_SNOOPING: g_value_set_boolean (value, priv->multicast_snooping); break; @@ -392,8 +425,13 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) * NMSettingBridge:mac-address: * * If specified, the MAC address of bridge. When creating a new bridge, this - * MAC address will be set. When matching an existing (outside - * NetworkManager created) bridge, this MAC address must match. + * MAC address will be set. + * + * If this field is left unspecified, the "ethernet.cloned-mac-address" is + * referred instead to generate the initial MAC address. Note that setting + * "ethernet.cloned-mac-address" anyway overwrites the MAC address of + * the bridge later while activating the bridge. Hence, this property + * is deprecated. **/ /* ---keyfile--- * property: mac-address @@ -557,6 +595,27 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class) G_PARAM_STATIC_STRINGS)); /** + * NMSettingBridge:group-forward-mask: + * + * A mask of group addresses to forward. Usually, group addresses in + * the range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not + * forwarded according to standards. This property is a mask of 16 bits, + * each corresponding to a group address in that range that must be + * forwarded. The mask can't have bits 0, 1 or 2 set because they are + * used for STP, MAC pause frames and LACP. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_GROUP_FORWARD_MASK, + g_param_spec_uint (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "", "", + 0, 0xFFFF, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** * NMSettingBridge:multicast-snooping: * * Controls whether IGMP snooping is enabled for this bridge. diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h index 81e4c644..d640dde3 100644 --- a/libnm-core/nm-setting-bridge.h +++ b/libnm-core/nm-setting-bridge.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS #define NM_SETTING_BRIDGE_HELLO_TIME "hello-time" #define NM_SETTING_BRIDGE_MAX_AGE "max-age" #define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time" +#define NM_SETTING_BRIDGE_GROUP_FORWARD_MASK "group-forward-mask" #define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping" /** @@ -81,6 +82,8 @@ guint16 nm_setting_bridge_get_hello_time (NMSettingBridge *setting); guint16 nm_setting_bridge_get_max_age (NMSettingBridge *setting); guint32 nm_setting_bridge_get_ageing_time (NMSettingBridge *setting); +NM_AVAILABLE_IN_1_10 +guint16 nm_setting_bridge_get_group_forward_mask (NMSettingBridge *setting); gboolean nm_setting_bridge_get_multicast_snooping (NMSettingBridge *setting); diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c index b267ba63..63178951 100644 --- a/libnm-core/nm-setting-cdma.c +++ b/libnm-core/nm-setting-cdma.c @@ -38,7 +38,7 @@ */ G_DEFINE_TYPE_WITH_CODE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING, - _nm_register_setting (CDMA, 1)) + _nm_register_setting (CDMA, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CDMA) #define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate)) diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index bf205e9a..24c65e7c 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -46,7 +46,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING, - _nm_register_setting (CONNECTION, 0)) + _nm_register_setting (CONNECTION, NM_SETTING_PRIORITY_CONNECTION)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CONNECTION) #define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate)) @@ -80,6 +80,7 @@ typedef struct { guint gateway_ping_timeout; NMMetered metered; NMSettingConnectionLldp lldp; + gint auth_retries; } NMSettingConnectionPrivate; enum { @@ -103,6 +104,7 @@ enum { PROP_METERED, PROP_LLDP, PROP_STABLE_ID, + PROP_AUTH_RETRIES, LAST_PROP }; @@ -553,6 +555,25 @@ nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting) } /** + * nm_setting_connection_get_auth_retries: + * @setting: the #NMSettingConnection + * + * Returns the value contained in the #NMSettingConnection:auth-retries property. + * + * Returns: the configured authentication retries. Zero means + * infinity and -1 means a global default value. + * + * Since: 1.10 + **/ +gint +nm_setting_connection_get_auth_retries (NMSettingConnection *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1); + + return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->auth_retries; +} + +/** * nm_setting_connection_get_timestamp: * @setting: the #NMSettingConnection * @@ -859,6 +880,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) gboolean is_slave; const char *slave_setting_type; NMSetting *normerr_base_type = NULL; + const char *type; + const char *slave_type; const char *normerr_slave_setting_type = NULL; const char *normerr_missing_slave_type = NULL; const char *normerr_missing_slave_type_port = NULL; @@ -904,8 +927,10 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - if (!priv->type) { - if (!connection || !(normerr_base_type = _nm_connection_find_base_type_setting (connection))) { + type = priv->type; + if (!type) { + if ( !connection + || !(normerr_base_type = _nm_connection_find_base_type_setting (connection))) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY, @@ -913,10 +938,11 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE); return FALSE; } + type = nm_setting_get_name (normerr_base_type); } else { GType base_type; - if (!priv->type[0]) { + if (!type[0]) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -925,20 +951,21 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - base_type = nm_setting_lookup_type (priv->type); - if (base_type == G_TYPE_INVALID || !_nm_setting_type_is_base_type (base_type)) { + base_type = nm_setting_lookup_type (type); + if ( base_type == G_TYPE_INVALID + || _nm_setting_type_get_base_type_priority (base_type) == NM_SETTING_PRIORITY_INVALID) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("connection type '%s' is not valid"), - priv->type); + type); g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE); return FALSE; } /* Make sure the corresponding 'type' item is present */ if ( connection - && !nm_connection_get_setting_by_name (connection, priv->type)) { + && !nm_connection_get_setting_by_name (connection, type)) { NMSetting *s_base; NMConnection *connection2; @@ -951,7 +978,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_object_unref (connection2); if (!normerr_base_setting) { - _set_error_missing_base_setting (error, priv->type); + _set_error_missing_base_setting (error, type); return FALSE; } } @@ -959,13 +986,14 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) is_slave = FALSE; slave_setting_type = NULL; - if (priv->slave_type) { - is_slave = _nm_setting_slave_type_is_valid (priv->slave_type, &slave_setting_type); + slave_type = priv->slave_type; + if (slave_type) { + is_slave = _nm_setting_slave_type_is_valid (slave_type, &slave_setting_type); if (!is_slave) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("Unknown slave type '%s'"), priv->slave_type); + _("Unknown slave type '%s'"), slave_type); g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE); return FALSE; } @@ -985,8 +1013,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) && !nm_connection_get_setting_by_name (connection, slave_setting_type)) normerr_slave_setting_type = slave_setting_type; } else { + nm_assert (!slave_type); if (priv->master) { - const char *slave_type; NMSetting *s_port; if ( connection @@ -1005,6 +1033,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } + if ( nm_streq0 (type, NM_SETTING_OVS_PORT_SETTING_NAME) + && !nm_streq0 (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Only '%s' connections can be enslaved to '%s'"), + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + if (priv->metered != NM_METERED_UNKNOWN && priv->metered != NM_METERED_YES && priv->metered != NM_METERED_NO) { @@ -1289,6 +1329,9 @@ set_property (GObject *object, guint prop_id, case PROP_LLDP: priv->lldp = g_value_get_int (value); break; + case PROP_AUTH_RETRIES: + priv->auth_retries = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1374,6 +1417,9 @@ get_property (GObject *object, guint prop_id, case PROP_LLDP: g_value_set_int (value, priv->lldp); break; + case PROP_AUTH_RETRIES: + g_value_set_int (value, priv->auth_retries); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1462,7 +1508,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) * hosts/devices yields different addresses. * * If the value is unset, an ID unique for the connection is used. - * Specifing a stable-id allows multiple connections to generate the + * Specifying a stable-id allows multiple connections to generate the * same addresses. Another use is to generate IDs at runtime via * dynamic substitutions. * @@ -1644,9 +1690,11 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) /** * NMSettingConnection:autoconnect-retries: * - * The number of times a connection should be tried when autoctivating before + * The number of times a connection should be tried when autoactivating before * giving up. Zero means forever, -1 means the global default (4 times if not - * overridden). + * overridden). Setting this to 1 means to try activation only once before + * blocking autoconnect. Note that after a timeout, NetworkManager will try + * to autoconnect again. */ /* ---ifcfg-rh--- * property: autoconnect-retries @@ -1907,4 +1955,31 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingConnection:auth-retries: + * + * The number of retries for the authentication. Zero means to try indefinitely; -1 means + * to use a global default. If the global default is not set, the authentication + * retries for 3 times before failing the connection. + * + * Currently this only applies to 802-1x authentication. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: auth-retries + * variable: AUTH_RETRIES(+) + * default: 0 + * description: Number of retries for authentication. + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_AUTH_RETRIES, + g_param_spec_int (NM_SETTING_CONNECTION_AUTH_RETRIES, "", "", + -1, G_MAXINT32, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h index bd5b98ff..02a7f5b1 100644 --- a/libnm-core/nm-setting-connection.h +++ b/libnm-core/nm-setting-connection.h @@ -63,6 +63,7 @@ G_BEGIN_DECLS #define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout" #define NM_SETTING_CONNECTION_METERED "metered" #define NM_SETTING_CONNECTION_LLDP "lldp" +#define NM_SETTING_CONNECTION_AUTH_RETRIES "auth-retries" /* Types for property values */ /** @@ -166,6 +167,9 @@ NMMetered nm_setting_connection_get_metered (NMSettingConnection *setting); NM_AVAILABLE_IN_1_2 NMSettingConnectionLldp nm_setting_connection_get_lldp (NMSettingConnection *setting); +NM_AVAILABLE_IN_1_10 +gint nm_setting_connection_get_auth_retries (NMSettingConnection *setting); + G_END_DECLS #endif /* __NM_SETTING_CONNECTION_H__ */ diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c index 140dc021..24d461a1 100644 --- a/libnm-core/nm-setting-dcb.c +++ b/libnm-core/nm-setting-dcb.c @@ -41,7 +41,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING, - _nm_register_setting (DCB, 2)) + _nm_register_setting (DCB, NM_SETTING_PRIORITY_HW_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DCB) #define NM_SETTING_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate)) @@ -1182,7 +1182,7 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) * An array of 8 uint values, where the array index corresponds to the * Priority Group ID (0 - 7) and the value indicates the percentage of link * bandwidth allocated to that group. Allowed values are 0 - 100, and the - * sum of all values must total 100 percent. + * sum of all values must total 100 percents. * * Element-type: guint **/ @@ -1211,7 +1211,7 @@ nm_setting_dcb_class_init (NMSettingDcbClass *setting_class) * Priority (0 - 7) and the value indicates the percentage of bandwidth of * the priority's assigned group that the priority may use. The sum of all * percentages for priorities which belong to the same group must total 100 - * percent. + * percents. * * Element-type: guint **/ diff --git a/libnm-core/nm-setting-dummy.c b/libnm-core/nm-setting-dummy.c index d23f0a30..4b3c41f0 100644 --- a/libnm-core/nm-setting-dummy.c +++ b/libnm-core/nm-setting-dummy.c @@ -35,7 +35,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING, - _nm_register_setting (DUMMY, 1)) + _nm_register_setting (DUMMY, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DUMMY) /** diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c index 09edeb6e..96f26ac2 100644 --- a/libnm-core/nm-setting-generic.c +++ b/libnm-core/nm-setting-generic.c @@ -37,7 +37,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING, - _nm_register_setting (GENERIC, 1)) + _nm_register_setting (GENERIC, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GENERIC) #define NM_SETTING_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate)) diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c index be32b852..3011d917 100644 --- a/libnm-core/nm-setting-gsm.c +++ b/libnm-core/nm-setting-gsm.c @@ -39,7 +39,7 @@ */ G_DEFINE_TYPE_WITH_CODE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING, - _nm_register_setting (GSM, 1)) + _nm_register_setting (GSM, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GSM) #define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate)) @@ -793,7 +793,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class) * mobile network operator which this connection applies to. If given, * the connection will apply to any device also allowed by * #NMSettingGsm:device-id and #NMSettingGsm:sim-id which contains a SIM - * card provisioined by the given operator. + * card provisioned by the given operator. * * Since: 1.2 **/ diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c index 1bbe2b3f..8c49849a 100644 --- a/libnm-core/nm-setting-infiniband.c +++ b/libnm-core/nm-setting-infiniband.c @@ -38,7 +38,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING, - _nm_register_setting (INFINIBAND, 1)) + _nm_register_setting (INFINIBAND, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_INFINIBAND) #define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate)) @@ -181,7 +181,7 @@ nm_setting_infiniband_get_virtual_interface_name (NMSettingInfiniband *setting) static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { - NMSettingConnection *s_con; + NMSettingConnection *s_con = NULL; NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting); guint32 normerr_max_mtu = 0; @@ -241,7 +241,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } - s_con = nm_connection_get_setting_connection (connection); + if (connection) + s_con = nm_connection_get_setting_connection (connection); if (s_con) { const char *interface_name = nm_setting_connection_get_interface_name (s_con); GError *tmp_error = NULL; diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 139c2c3e..7265fdc5 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -753,18 +753,22 @@ nm_ip_route_unref (NMIPRoute *route) } /** - * _nm_ip_route_equal: + * nm_ip_route_equal_full: * @route: the #NMIPRoute * @other: the #NMIPRoute to compare @route to. - * @consider_attributes: whether to compare attributes too + * @cmp_flags: tune how to compare attributes. Currently only + * NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE (0) and NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS (1) + * is supported. * * Determines if two #NMIPRoute objects contain the same destination, prefix, * next hop, and metric. * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. + * + * Since: 1.10 **/ -static gboolean -_nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other, gboolean consider_attributes) +gboolean +nm_ip_route_equal_full (NMIPRoute *route, NMIPRoute *other, guint cmp_flags) { g_return_val_if_fail (route != NULL, FALSE); g_return_val_if_fail (route->refcount > 0, FALSE); @@ -772,12 +776,16 @@ _nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other, gboolean consider_attrib g_return_val_if_fail (other != NULL, FALSE); g_return_val_if_fail (other->refcount > 0, FALSE); + g_return_val_if_fail (NM_IN_SET (cmp_flags, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS), FALSE); + if ( route->prefix != other->prefix || route->metric != other->metric || strcmp (route->dest, other->dest) != 0 || g_strcmp0 (route->next_hop, other->next_hop) != 0) return FALSE; - if (consider_attributes) { + if (cmp_flags == NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS) { GHashTableIter iter; const char *key; GVariant *value, *value2; @@ -813,7 +821,7 @@ _nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other, gboolean consider_attrib gboolean nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other) { - return _nm_ip_route_equal (route, other, FALSE); + return nm_ip_route_equal_full (route, other, NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE); } /** @@ -1104,6 +1112,54 @@ nm_ip_route_set_metric (NMIPRoute *route, route->metric = metric; } +GHashTable * +_nm_ip_route_get_attributes_direct (NMIPRoute *route) +{ + nm_assert (route); + + return route->attributes; +} + +/** + * _nm_ip_route_get_attribute_names: + * @route: the #NMIPRoute + * @sorted: whether to sort the names. Otherwise, their order is + * undefined and unstable. + * @out_length: (allow-none): (out): the number of elements + * + * Gets an array of attribute names defined on @route. + * + * Returns: (array length=out_length) (transfer container): a %NULL-terminated array + * of attribute names or %NULL if there are no attributes. The order of the returned + * names is undefined. + **/ +const char ** +_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length) +{ + const char **names; + guint length; + + g_return_val_if_fail (route != NULL, NULL); + + if ( !route->attributes + || !g_hash_table_size (route->attributes)) { + NM_SET_OUT (out_length, 0); + return NULL; + } + + names = (const char **) g_hash_table_get_keys_as_array (route->attributes, &length); + if ( sorted + && length > 1) { + g_qsort_with_data (names, + length, + sizeof (char *), + nm_strcmp_p_with_data, + NULL); + } + NM_SET_OUT (out_length, length); + return names; +} + /** * nm_ip_route_get_attribute_names: * @route: the #NMIPRoute @@ -1115,22 +1171,21 @@ nm_ip_route_set_metric (NMIPRoute *route, char ** nm_ip_route_get_attribute_names (NMIPRoute *route) { - GHashTableIter iter; - const char *key; - GPtrArray *names; + char **names; + guint i, len; g_return_val_if_fail (route != NULL, NULL); - names = g_ptr_array_new (); + names = (char **) _nm_ip_route_get_attribute_names (route, TRUE, &len); + if (!names) + return g_new0 (char *, 1); - if (route->attributes) { - g_hash_table_iter_init (&iter, route->attributes); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) - g_ptr_array_add (names, g_strdup (key)); + nm_assert (len > 0 && names && names[len] == NULL); + for (i = 0; i < len; i++) { + nm_assert (names[i]); + names[i] = g_strdup (names[i]); } - g_ptr_array_add (names, NULL); - - return (char **) g_ptr_array_free (names, FALSE); + return names; } /** @@ -1186,9 +1241,10 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value) &(NMVariantAttributeSpec) { name, type, v4, v6, str_type } static const NMVariantAttributeSpec * const ip_route_attribute_spec[] = { + ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, TRUE, TRUE, 'a'), ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_FROM, G_VARIANT_TYPE_STRING, FALSE, TRUE, 'p'), - ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, TRUE, 0 ), + ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, TRUE, FALSE, 0 ), ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_CWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), ATTR_SPEC_PTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND, G_VARIANT_TYPE_UINT32, TRUE, TRUE, 0 ), @@ -1289,7 +1345,7 @@ nm_ip_route_attribute_validate (const char *name, char *sep; switch (spec->str_type) { - case 'a': /* IP address */ + case 'a': /* IP address */ if (!nm_utils_ipaddr_valid (family, string)) { g_set_error (error, NM_CONNECTION_ERROR, @@ -1301,7 +1357,7 @@ nm_ip_route_attribute_validate (const char *name, return FALSE; } break; - case 'p': /* IP address + optional prefix */ + case 'p': /* IP address + optional prefix */ string_free = g_strdup (string); sep = strchr (string_free, '/'); if (sep) { @@ -1333,6 +1389,26 @@ nm_ip_route_attribute_validate (const char *name, return TRUE; } +gboolean +_nm_ip_route_attribute_validate_all (const NMIPRoute *route) +{ + GHashTableIter iter; + const char *key; + GVariant *val; + + g_return_val_if_fail (route, FALSE); + + if (!route->attributes) + return TRUE; + + g_hash_table_iter_init (&iter, route->attributes); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { + if (!nm_ip_route_attribute_validate (key, val, route->family, NULL, NULL)) + return FALSE; + } + return TRUE; +} + /*****************************************************************************/ G_DEFINE_ABSTRACT_TYPE (NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING) @@ -1348,6 +1424,7 @@ typedef struct { GPtrArray *addresses; /* array of NMIPAddress */ GPtrArray *routes; /* array of NMIPRoute */ gint64 route_metric; + guint32 route_table; char *gateway; gboolean ignore_auto_routes; gboolean ignore_auto_dns; @@ -1370,6 +1447,7 @@ enum { PROP_GATEWAY, PROP_ROUTES, PROP_ROUTE_METRIC, + PROP_ROUTE_TABLE, PROP_IGNORE_AUTO_ROUTES, PROP_IGNORE_AUTO_DNS, PROP_DHCP_HOSTNAME, @@ -1429,7 +1507,7 @@ nm_setting_ip_config_get_dns (NMSettingIPConfig *setting, int idx) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_val_if_fail (idx < priv->dns->len, NULL); + g_return_val_if_fail (idx >= 0 && idx < priv->dns->len, NULL); return priv->dns->pdata[idx]; } @@ -1449,7 +1527,7 @@ nm_setting_ip_config_add_dns (NMSettingIPConfig *setting, const char *dns) { NMSettingIPConfigPrivate *priv; char *dns_canonical; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns != NULL, FALSE); @@ -1485,7 +1563,7 @@ nm_setting_ip_config_remove_dns (NMSettingIPConfig *setting, int idx) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_if_fail (idx < priv->dns->len); + g_return_if_fail (idx >= 0 && idx < priv->dns->len); g_ptr_array_remove_index (priv->dns, idx); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS); @@ -1505,7 +1583,7 @@ nm_setting_ip_config_remove_dns_by_value (NMSettingIPConfig *setting, const char { NMSettingIPConfigPrivate *priv; char *dns_canonical; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns != NULL, FALSE); @@ -1573,7 +1651,7 @@ nm_setting_ip_config_get_dns_search (NMSettingIPConfig *setting, int idx) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_val_if_fail (idx < priv->dns_search->len, NULL); + g_return_val_if_fail (idx >= 0 && idx < priv->dns_search->len, NULL); return priv->dns_search->pdata[idx]; } @@ -1593,7 +1671,7 @@ nm_setting_ip_config_add_dns_search (NMSettingIPConfig *setting, const char *dns_search) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns_search != NULL, FALSE); @@ -1625,7 +1703,7 @@ nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int idx) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_if_fail (idx < priv->dns_search->len); + g_return_if_fail (idx >= 0 && idx < priv->dns_search->len); g_ptr_array_remove_index (priv->dns_search, idx); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH); @@ -1647,7 +1725,7 @@ nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig *setting, const char *dns_search) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns_search != NULL, FALSE); @@ -1832,7 +1910,7 @@ nm_setting_ip_config_remove_dns_option (NMSettingIPConfig *setting, int idx) priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); g_return_if_fail (priv->dns_options); - g_return_if_fail (idx < priv->dns_options->len); + g_return_if_fail (idx >= 0 && idx < priv->dns_options->len); g_ptr_array_remove_index (priv->dns_options, idx); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS); @@ -1854,7 +1932,7 @@ nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting, const char *dns_option) { NMSettingIPConfigPrivate *priv; - int i; + gssize i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (dns_option != NULL, FALSE); @@ -1954,7 +2032,7 @@ nm_setting_ip_config_get_address (NMSettingIPConfig *setting, int idx) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_val_if_fail (idx < priv->addresses->len, NULL); + g_return_val_if_fail (idx >= 0 && idx < priv->addresses->len, NULL); return priv->addresses->pdata[idx]; } @@ -1975,7 +2053,7 @@ nm_setting_ip_config_add_address (NMSettingIPConfig *setting, NMIPAddress *address) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (address != NULL, FALSE); @@ -2008,7 +2086,7 @@ nm_setting_ip_config_remove_address (NMSettingIPConfig *setting, int idx) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_if_fail (idx < priv->addresses->len); + g_return_if_fail (idx >= 0 && idx < priv->addresses->len); g_ptr_array_remove_index (priv->addresses, idx); @@ -2029,7 +2107,7 @@ nm_setting_ip_config_remove_address_by_value (NMSettingIPConfig *setting, NMIPAddress *address) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (address != NULL, FALSE); @@ -2106,7 +2184,7 @@ nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int idx) g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_val_if_fail (idx < priv->routes->len, NULL); + g_return_val_if_fail (idx >= 0 && idx < priv->routes->len, NULL); return priv->routes->pdata[idx]; } @@ -2116,8 +2194,14 @@ nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int idx) * @setting: the #NMSettingIPConfig * @route: the route to add * - * Adds a new route and associated information to the setting. The + * Appends a new route and associated information to the setting. The * given route is duplicated internally and is not changed by this function. + * If an identical route (considering attributes as well) already exists, the + * route is not added and the function returns %FALSE. + * + * Note that before 1.10, this function would not consider route attributes + * and not add a route that has an existing route with same dest/prefix,next_hop,metric + * parameters. * * Returns: %TRUE if the route was added; %FALSE if the route was already known. **/ @@ -2126,7 +2210,7 @@ nm_setting_ip_config_add_route (NMSettingIPConfig *setting, NMIPRoute *route) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (route != NULL, FALSE); @@ -2134,7 +2218,7 @@ nm_setting_ip_config_add_route (NMSettingIPConfig *setting, priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal (priv->routes->pdata[i], route)) + if (nm_ip_route_equal_full (priv->routes->pdata[i], route, NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) return FALSE; } @@ -2158,7 +2242,7 @@ nm_setting_ip_config_remove_route (NMSettingIPConfig *setting, int idx) g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting)); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - g_return_if_fail (idx < priv->routes->len); + g_return_if_fail (idx >= 0 && idx < priv->routes->len); g_ptr_array_remove_index (priv->routes, idx); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES); @@ -2169,23 +2253,25 @@ nm_setting_ip_config_remove_route (NMSettingIPConfig *setting, int idx) * @setting: the #NMSettingIPConfig * @route: the route to remove * - * Removes the route @route. + * Removes the first matching route that matches @route. + * Note that before 1.10, this function would only compare dest/prefix,next_hop,metric + * and ignore route attributes. Now, @route must match exactly. * * Returns: %TRUE if the route was found and removed; %FALSE if it was not. **/ gboolean nm_setting_ip_config_remove_route_by_value (NMSettingIPConfig *setting, - NMIPRoute *route) + NMIPRoute *route) { NMSettingIPConfigPrivate *priv; - int i; + guint i; g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE); g_return_val_if_fail (route != NULL, FALSE); priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); for (i = 0; i < priv->routes->len; i++) { - if (nm_ip_route_equal (priv->routes->pdata[i], route)) { + if (nm_ip_route_equal_full (priv->routes->pdata[i], route, NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { g_ptr_array_remove_index (priv->routes, i); g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES); return TRUE; @@ -2229,6 +2315,24 @@ nm_setting_ip_config_get_route_metric (NMSettingIPConfig *setting) return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_metric; } +/** + * nm_setting_ip_config_get_route_table: + * @setting: the #NMSettingIPConfig + * + * Returns the value contained in the #NMSettingIPConfig:route-table + * property. + * + * Returns: the configured route-table. + * + * Since: 1.10 + **/ +guint32 +nm_setting_ip_config_get_route_table (NMSettingIPConfig *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_table; +} /** * nm_setting_ip_config_get_ignore_auto_routes: @@ -2402,7 +2506,7 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); - int i; + guint i; if (!priv->method) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY, @@ -2427,7 +2531,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. DNS server address is invalid"), - i+1); + (int) (i + 1)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_DNS); return FALSE; } @@ -2443,7 +2547,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. IP address is invalid"), - i+1); + (int) (i + 1)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES); return FALSE; } @@ -2455,7 +2559,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. IP address has 'label' property with invalid type"), - i+1); + (int) (i + 1)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES); return FALSE; } @@ -2464,7 +2568,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. IP address has invalid label '%s'"), - i+1, g_variant_get_string (label, NULL)); + (int) (i + 1), g_variant_get_string (label, NULL)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES); return FALSE; } @@ -2501,7 +2605,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. route is invalid"), - i+1); + (int) (i + 1)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES); return FALSE; } @@ -2510,7 +2614,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("%d. route cannot be a default route"), - i+1); + (int) (i + 1)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES); return FALSE; } @@ -2559,7 +2663,7 @@ compare_property (NMSetting *setting, if (a_priv->routes->len != b_priv->routes->len) return FALSE; for (i = 0; i < a_priv->routes->len; i++) { - if (!_nm_ip_route_equal (a_priv->routes->pdata[i], b_priv->routes->pdata[i], TRUE)) + if (!nm_ip_route_equal_full (a_priv->routes->pdata[i], b_priv->routes->pdata[i], NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) return FALSE; } return TRUE; @@ -2612,7 +2716,7 @@ set_property (GObject *object, guint prop_id, NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); const char *gateway; char **strv; - int i; + guint i; switch (prop_id) { case PROP_METHOD: @@ -2670,6 +2774,9 @@ set_property (GObject *object, guint prop_id, case PROP_ROUTE_METRIC: priv->route_metric = g_value_get_int64 (value); break; + case PROP_ROUTE_TABLE: + priv->route_table = g_value_get_uint (value); + break; case PROP_IGNORE_AUTO_ROUTES: priv->ignore_auto_routes = g_value_get_boolean (value); break; @@ -2740,6 +2847,9 @@ get_property (GObject *object, guint prop_id, case PROP_ROUTE_METRIC: g_value_set_int64 (value, priv->route_metric); break; + case PROP_ROUTE_TABLE: + g_value_set_uint (value, priv->route_table); + break; case PROP_IGNORE_AUTO_ROUTES: g_value_set_boolean (value, nm_setting_ip_config_get_ignore_auto_routes (setting)); break; @@ -2970,7 +3080,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) * NMSettingIPConfig:route-metric: * * The default metric for routes that don't explicitly specify a metric. - * The default value -1 means that the metric is choosen automatically + * The default value -1 means that the metric is chosen automatically * based on the device type. * The metric applies to dynamic routes, manual (static) routes that * don't have an explicit metric setting, address prefix routes, and @@ -2989,6 +3099,34 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) G_PARAM_STATIC_STRINGS)); /** + * NMSettingIPConfig:route-table: + * + * Enable policy routing (source routing) and set the routing table used when adding routes. + * + * This affects all routes, including device-routes, IPv4LL, DHCP, SLAAC, default-routes + * and static routes. But note that static routes can individually overwrite the setting + * by explicitly specifying a non-zero routing table. + * + * If the table setting is left at zero, it is eligible to be overwritten via global + * configuration. If the property is zero even after applying the global configuration + * value, policy routing is disabled for the address family of this connection. + * + * Policy routing disabled means that NetworkManager will add all routes to the main + * table (except static routes that explicitly configure a different table). Additionally, + * NetworkManager will not delete any extraneous routes from tables except the main table. + * This is to preserve backward compatibility for users who manage routing tables outside + * of NetworkManager. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_ROUTE_TABLE, + g_param_spec_uint (NM_SETTING_IP_CONFIG_ROUTE_TABLE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); + /** * NMSettingIPConfig:ignore-auto-routes: * * When #NMSettingIPConfig:method is set to "auto" and this property to @@ -3106,6 +3244,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_STATIC_STRINGS)); + /** * NMSettingIPConfig:dhcp-timeout: * diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index b7bb0215..84ce8465 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -92,6 +92,17 @@ void nm_ip_route_ref (NMIPRoute *route); void nm_ip_route_unref (NMIPRoute *route); gboolean nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other); + +enum { + NM_IP_ROUTE_EQUAL_CMP_FLAGS_NONE = 0, + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS = (1LL << 0), +}; + +NM_AVAILABLE_IN_1_10 +gboolean nm_ip_route_equal_full (NMIPRoute *route, + NMIPRoute *other, + guint cmp_flags); + NMIPRoute *nm_ip_route_dup (NMIPRoute *route); int nm_ip_route_get_family (NMIPRoute *route); @@ -131,6 +142,7 @@ gboolean nm_ip_route_attribute_validate (const char *name, gboolean *known, GError **error); +#define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" #define NM_IP_ROUTE_ATTRIBUTE_SRC "src" #define NM_IP_ROUTE_ATTRIBUTE_FROM "from" #define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" @@ -163,6 +175,7 @@ gboolean nm_ip_route_attribute_validate (const char *name, #define NM_SETTING_IP_CONFIG_GATEWAY "gateway" #define NM_SETTING_IP_CONFIG_ROUTES "routes" #define NM_SETTING_IP_CONFIG_ROUTE_METRIC "route-metric" +#define NM_SETTING_IP_CONFIG_ROUTE_TABLE "route-table" #define NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" #define NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" #define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME "dhcp-hostname" @@ -271,6 +284,9 @@ void nm_setting_ip_config_clear_routes (NMSettingIPConfig gint64 nm_setting_ip_config_get_route_metric (NMSettingIPConfig *setting); +NM_AVAILABLE_IN_1_10 +guint32 nm_setting_ip_config_get_route_table (NMSettingIPConfig *setting); + gboolean nm_setting_ip_config_get_ignore_auto_routes (NMSettingIPConfig *setting); gboolean nm_setting_ip_config_get_ignore_auto_dns (NMSettingIPConfig *setting); diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 4589f766..fa8d4a7a 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -31,7 +31,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING, - _nm_register_setting (IP_TUNNEL, 1)) + _nm_register_setting (IP_TUNNEL, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP_TUNNEL) #define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate)) @@ -758,7 +758,7 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class) G_PARAM_STATIC_STRINGS)); /** - * NMSettingIPTunel:mtu: + * NMSettingIPTunnel:mtu: * * If non-zero, only transmit packets of the specified size or smaller, * breaking larger packets up into multiple fragments. diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index 3f396b75..db3a12be 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -51,7 +51,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP4_CONFIG, 4)) + _nm_register_setting (IP4_CONFIG, NM_SETTING_PRIORITY_IP)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG) #define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate)) @@ -681,6 +681,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) */ /* ---ifcfg-rh--- + * property: route-table + * variable: IPV4_ROUTE_TABLE(+) + * default: 0 + * description: IPV4_ROUTE_TABLE enables policy-routing and sets the default routing table. + * ---end--- + */ + + /* ---ifcfg-rh--- * property: dns-priority * variable: IPV4_DNS_PRIORITY(+) * description: The priority for DNS servers of this connection. Lower values have higher priority. diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index 429f27c9..cc6381f0 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -52,7 +52,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG, - _nm_register_setting (IP6_CONFIG, 4)) + _nm_register_setting (IP6_CONFIG, NM_SETTING_PRIORITY_IP)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG) #define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate)) @@ -224,7 +224,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("property is invalid")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE); return FALSE; } @@ -653,6 +653,14 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) */ /* ---ifcfg-rh--- + * property: route-table + * variable: IPV6_ROUTE_TABLE(+) + * default: 0 + * description: IPV6_ROUTE_TABLE enables policy-routing and sets the default routing table. + * ---end--- + */ + + /* ---ifcfg-rh--- * property: dns-priority * variable: IPV6_DNS_PRIORITY(+) * description: The priority for DNS servers of this connection. Lower values have higher priority. @@ -707,16 +715,17 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * NMSettingIP6Config:addr-gen-mode: * * Configure method for creating the address for use with RFC4862 IPv6 - * Stateless Address Autoconfiguration. The permitted values are: "eui64", - * or "stable-privacy". + * Stateless Address Autoconfiguration. The permitted values are: + * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 or + * %NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY. * - * If the property is set to "eui64", the addresses will be generated - * using the interface tokens derived from hardware address. This makes + * If the property is set to EUI64, the addresses will be generated + * using the interface tokens derived from hardware address. This makes * the host part of the address to stay constant, making it possible * to track host's presence when it changes networks. The address changes * when the interface hardware is replaced. * - * The value of "stable-privacy" enables use of cryptographically + * The value of stable-privacy enables use of cryptographically * secure hash of a secret host-specific key along with the connection's * stable-id and the network address as specified by RFC7217. * This makes it impossible to use the address track host's presence, @@ -724,8 +733,8 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * replaced. * * On D-Bus, the absence of an addr-gen-mode setting equals enabling - * "stable-privacy". For keyfile plugin, the absence of the setting - * on disk means "eui64" so that the property doesn't change on upgrade + * stable-privacy. For keyfile plugin, the absence of the setting + * on disk means EUI64 so that the property doesn't change on upgrade * from older versions. * * Note that this setting is distinct from the Privacy Extensions as diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c index c818f07f..7a8a5a34 100644 --- a/libnm-core/nm-setting-macsec.c +++ b/libnm-core/nm-setting-macsec.c @@ -41,7 +41,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING, - _nm_register_setting (MACSEC, 1)) + _nm_register_setting (MACSEC, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACSEC) #define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate)) diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c index f5edc6e8..d684e58d 100644 --- a/libnm-core/nm-setting-macvlan.c +++ b/libnm-core/nm-setting-macvlan.c @@ -40,7 +40,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING, - _nm_register_setting (MACVLAN, 1)) + _nm_register_setting (MACVLAN, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACVLAN) #define NM_SETTING_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate)) diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c index eba29c92..783d143f 100644 --- a/libnm-core/nm-setting-olpc-mesh.c +++ b/libnm-core/nm-setting-olpc-mesh.c @@ -40,7 +40,7 @@ static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting); G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING, - _nm_register_setting (OLPC_MESH, 1)) + _nm_register_setting (OLPC_MESH, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OLPC_MESH) #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate)) diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c new file mode 100644 index 00000000..fbae95d0 --- /dev/null +++ b/libnm-core/nm-setting-ovs-bridge.c @@ -0,0 +1,337 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ovs-bridge.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-bridge + * @short_description: Describes connection properties for OpenVSwitch bridges. + * + * The #NMSettingOvsBridge object is a #NMSetting subclass that describes properties + * necessary for OpenVSwitch bridges. + **/ + +enum { + PROP_0, + PROP_FAIL_MODE, + PROP_MCAST_SNOOPING_ENABLE, + PROP_RSTP_ENABLE, + PROP_STP_ENABLE, + LAST_PROP +}; + +/** + * NMSettingOvsBridge: + * + * OvsBridge Link Settings + */ +struct _NMSettingOvsBridge { + NMSetting parent; + + char *fail_mode; + gboolean mcast_snooping_enable; + gboolean rstp_enable; + gboolean stp_enable; +}; + +struct _NMSettingOvsBridgeClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE_WITH_CODE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING, + _nm_register_setting (OVS_BRIDGE, NM_SETTING_PRIORITY_HW_BASE)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_BRIDGE) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_bridge_get_fail_mode: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:fail_mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_bridge_get_fail_mode (NMSettingOvsBridge *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_BRIDGE (self), NULL); + + return self->fail_mode; +} + +/** + * nm_setting_ovs_bridge_get_mcast_snooping_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:mcast_snooping_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_mcast_snooping_enable (NMSettingOvsBridge *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_BRIDGE (self), FALSE); + + return self->mcast_snooping_enable; +} + +/** + * nm_setting_ovs_bridge_get_rstp_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:rstp_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_rstp_enable (NMSettingOvsBridge *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_BRIDGE (self), FALSE); + + return self->rstp_enable; +} + +/** + * nm_setting_ovs_bridge_get_stp_enable: + * @self: the #NMSettingOvsBridge + * + * Returns: the #NMSettingOvsBridge:stp_enable property of the setting + * + * Since: 1.10 + **/ +gboolean +nm_setting_ovs_bridge_get_stp_enable (NMSettingOvsBridge *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_BRIDGE (self), FALSE); + + return self->stp_enable; +} + +/*****************************************************************************/ + +static int +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE (setting); + + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + + if (connection) { + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (nm_setting_connection_get_master (s_con)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must not have a master."), + NM_SETTING_OVS_BRIDGE_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + } + + if (!NM_IN_STRSET (self->fail_mode, "secure", "standalone", NULL)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in fail_mode"), + self->fail_mode); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_BRIDGE_SETTING_NAME, NM_SETTING_OVS_BRIDGE_FAIL_MODE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE (object); + + switch (prop_id) { + case PROP_FAIL_MODE: + g_value_set_string (value, self->fail_mode); + break; + case PROP_MCAST_SNOOPING_ENABLE: + g_value_set_boolean (value, self->mcast_snooping_enable); + break; + case PROP_RSTP_ENABLE: + g_value_set_boolean (value, self->rstp_enable); + break; + case PROP_STP_ENABLE: + g_value_set_boolean (value, self->stp_enable); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE (object); + + switch (prop_id) { + case PROP_FAIL_MODE: + g_free (self->fail_mode); + self->fail_mode = g_value_dup_string (value); + break; + case PROP_MCAST_SNOOPING_ENABLE: + self->mcast_snooping_enable = g_value_get_boolean (value); + break; + case PROP_RSTP_ENABLE: + self->rstp_enable = g_value_get_boolean (value); + break; + case PROP_STP_ENABLE: + self->stp_enable = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_bridge_init (NMSettingOvsBridge *self) +{ +} + +/** + * nm_setting_ovs_bridge_new: + * + * Creates a new #NMSettingOvsBridge object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsBridge object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_bridge_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_OVS_BRIDGE, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingOvsBridge *self = NM_SETTING_OVS_BRIDGE (object); + + g_free (self->fail_mode); + + G_OBJECT_CLASS (nm_setting_ovs_bridge_parent_class)->finalize (object); +} + +static void +nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /** + * NMSettingOvsBridge:fail-mode: + * + * The bridge failure mode. One of "secure", "standalone" or empty. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_FAIL_MODE, + g_param_spec_string (NM_SETTING_OVS_BRIDGE_FAIL_MODE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsBridge:mcast-snooping-enable: + * + * Enable or disable multicast snooping. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_MCAST_SNOOPING_ENABLE, + g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsBridge:rstp-enable: + * + * Enable or disable RSTP. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_RSTP_ENABLE, + g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_RSTP_ENABLE, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsBridge:stp-enable: + * + * Enable or disable STP. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_STP_ENABLE, + g_param_spec_boolean (NM_SETTING_OVS_BRIDGE_STP_ENABLE, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-ovs-bridge.h b/libnm-core/nm-setting-ovs-bridge.h new file mode 100644 index 00000000..d4837e58 --- /dev/null +++ b/libnm-core/nm-setting-ovs-bridge.h @@ -0,0 +1,63 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_BRIDGE_H__ +#define __NM_SETTING_OVS_BRIDGE_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_BRIDGE (nm_setting_ovs_bridge_get_type ()) +#define NM_SETTING_OVS_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridge)) +#define NM_SETTING_OVS_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OVS_BRIDGECONFIG, NMSettingOvsBridgeClass)) +#define NM_IS_SETTING_OVS_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OVS_BRIDGE)) +#define NM_IS_SETTING_OVS_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_OVS_BRIDGE)) +#define NM_SETTING_OVS_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OVS_BRIDGE, NMSettingOvsBridgeClass)) + +#define NM_SETTING_OVS_BRIDGE_SETTING_NAME "ovs-bridge" + +#define NM_SETTING_OVS_BRIDGE_FAIL_MODE "fail-mode" +#define NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE "mcast-snooping-enable" +#define NM_SETTING_OVS_BRIDGE_RSTP_ENABLE "rstp-enable" +#define NM_SETTING_OVS_BRIDGE_STP_ENABLE "stp-enable" + +typedef struct _NMSettingOvsBridgeClass NMSettingOvsBridgeClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_bridge_get_type (void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_bridge_new (void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_bridge_get_fail_mode (NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_mcast_snooping_enable (NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_rstp_enable (NMSettingOvsBridge *self); +NM_AVAILABLE_IN_1_10 +gboolean nm_setting_ovs_bridge_get_stp_enable (NMSettingOvsBridge *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_BRIDGE_H__ */ diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c new file mode 100644 index 00000000..f06db32a --- /dev/null +++ b/libnm-core/nm-setting-ovs-interface.c @@ -0,0 +1,392 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ovs-interface.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-interface + * @short_description: Describes connection properties for OpenVSwitch interfaces. + * + * The #NMSettingOvsInterface object is a #NMSetting subclass that describes properties + * necessary for OpenVSwitch interfaces. + **/ + +enum { + PROP_0, + PROP_TYPE, + LAST_PROP +}; + +/** + * NMSettingOvsInterface: + * + * OpenVSwitch Interface Settings + */ +struct _NMSettingOvsInterface { + NMSetting parent; + + char *type; +}; + +struct _NMSettingOvsInterfaceClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE_WITH_CODE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING, + _nm_register_setting (OVS_INTERFACE, NM_SETTING_PRIORITY_HW_BASE)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_INTERFACE) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_interface_get_interface_type: + * @self: the #NMSettingOvsInterface + * + * Returns: the #NMSettingOvsInterface:type property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_interface_get_interface_type (NMSettingOvsInterface *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_INTERFACE (self), NULL); + + return self->type; +} + +/*****************************************************************************/ + +int +_nm_setting_ovs_interface_verify_interface_type (NMSettingOvsInterface *self, + NMConnection *connection, + gboolean normalize, + gboolean *out_modified, + GError **error) +{ + gboolean has_patch; + const char *type; + const char *connection_type; + gboolean is_ovs_connection_type; + gboolean missing_patch_setting = FALSE; + + g_return_val_if_fail (NM_IS_SETTING_OVS_INTERFACE (self), FALSE); + if (normalize) { + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + nm_assert (self == nm_connection_get_setting_ovs_interface (connection)); + } else + g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), FALSE); + + NM_SET_OUT (out_modified, FALSE); + + type = self ? self->type : NULL; + + if ( type + && !NM_IN_STRSET (type, + "internal", + "system", + "patch")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid interface type"), + type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + + if (!connection) + return TRUE; + + connection_type = nm_connection_get_connection_type (connection); + if (!connection_type) { + /* if we have an ovs-interface, then the connection type must be either + * "ovs-interface" (for non "system" type) or anything else (for "system" type). + * + * The connection type usually can be normalized based on the presence of a + * base setting. However, in this case, if the connection type is missing, + * that is too complicate to guess what the user wanted. + * + * Require the use to be explicit and fail. */ + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting needs connection.type explicitly set"), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE); + return FALSE; + } + + if (nm_streq (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME)) { + if ( type + && nm_streq (type, "system")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection of type '%s' cannot have ovs-interface.type \"system\""), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + is_ovs_connection_type = TRUE; + } else { + if ( type + && !nm_streq (type, "system")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection of type '%s' cannot have an ovs-interface.type \"%s\""), + connection_type, + type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + is_ovs_connection_type = FALSE; + } + + has_patch = !!nm_connection_get_setting_by_name (connection, NM_SETTING_OVS_PATCH_SETTING_NAME); + + if (has_patch) { + if (!is_ovs_connection_type) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with '%s' setting must be of connection.type \"ovs-interface\" but is \"%s\""), + NM_SETTING_OVS_PATCH_SETTING_NAME, + connection_type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + if (type) { + if (!nm_streq (type, "patch")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with '%s' setting needs to be of 'patch' interface type, not '%s'"), + NM_SETTING_OVS_PATCH_SETTING_NAME, + type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + return TRUE; + } + type = "patch"; + goto normalize; + } else { + if (nm_streq0 (type, "patch")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("A connection with ovs-interface.type '%s' setting a 'ovs-patch' setting"), + type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + return FALSE; + } + } + + if (type) + return TRUE; + + if (is_ovs_connection_type) + type = "internal"; + else + type = "system"; +normalize: + if (!normalize) { + if (!self) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("Missing ovs interface setting")); + g_prefix_error (error, "%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME); + } else { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("Missing ovs interface type")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_INTERFACE_SETTING_NAME, NM_SETTING_OVS_INTERFACE_TYPE); + } + if (missing_patch_setting) { + } + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + + if (!self) { + self = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (connection, NM_SETTING (self)); + } + g_object_set (self, + NM_SETTING_OVS_INTERFACE_TYPE, type, + NULL); + NM_SET_OUT (out_modified, TRUE); + + return TRUE; +} + + +static int +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (setting); + + if (connection) { + NMSettingConnection *s_con; + const char *slave_type; + + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (!nm_setting_connection_get_master (s_con)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have a master."), + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type (s_con); + if ( slave_type + && !nm_streq (slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. Instead it is '%s'"), + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + slave_type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + return _nm_setting_ovs_interface_verify_interface_type (self, + connection, + FALSE, + NULL, + error); +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (object); + + switch (prop_id) { + case PROP_TYPE: + g_value_set_string (value, self->type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (object); + + switch (prop_id) { + case PROP_TYPE: + g_free (self->type); + self->type = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_interface_init (NMSettingOvsInterface *self) +{ +} + +/** + * nm_setting_ovs_interface_new: + * + * Creates a new #NMSettingOvsInterface object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsInterface object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_interface_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_OVS_INTERFACE, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingOvsInterface *self = NM_SETTING_OVS_INTERFACE (object); + + g_free (self->type); + + G_OBJECT_CLASS (nm_setting_ovs_interface_parent_class)->finalize (object); +} + +static void +nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /** + * NMSettingOvsInterface:type: + * + * The interface type. Either "internal", or empty. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_TYPE, + g_param_spec_string (NM_SETTING_OVS_INTERFACE_TYPE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-ovs-interface.h b/libnm-core/nm-setting-ovs-interface.h new file mode 100644 index 00000000..7261cfd8 --- /dev/null +++ b/libnm-core/nm-setting-ovs-interface.h @@ -0,0 +1,54 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_INTERFACE_H__ +#define __NM_SETTING_OVS_INTERFACE_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_get_type ()) +#define NM_SETTING_OVS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterface)) +#define NM_SETTING_OVS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OVS_INTERFACECONFIG, NMSettingOvsInterfaceClass)) +#define NM_IS_SETTING_OVS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OVS_INTERFACE)) +#define NM_IS_SETTING_OVS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_OVS_INTERFACE)) +#define NM_SETTING_OVS_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OVS_INTERFACE, NMSettingOvsInterfaceClass)) + +#define NM_SETTING_OVS_INTERFACE_SETTING_NAME "ovs-interface" + +#define NM_SETTING_OVS_INTERFACE_TYPE "type" + +typedef struct _NMSettingOvsInterfaceClass NMSettingOvsInterfaceClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_interface_get_type (void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_interface_new (void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_interface_get_interface_type (NMSettingOvsInterface *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_INTERFACE_H__ */ diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c new file mode 100644 index 00000000..9e380914 --- /dev/null +++ b/libnm-core/nm-setting-ovs-patch.c @@ -0,0 +1,215 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ovs-patch.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-patch + * @short_description: Describes connection properties for OpenVSwitch patch interfaces. + * + * The #NMSettingOvsPatch object is a #NMSetting subclass that describes properties + * necessary for OpenVSwitch interfaces of type "patch". + **/ + +enum { + PROP_0, + PROP_PEER, + LAST_PROP +}; + +/** + * NMSettingOvsPatch: + * + * OvsPatch Link Settings + */ +struct _NMSettingOvsPatch { + NMSetting parent; + + char *peer; +}; + +struct _NMSettingOvsPatchClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING, + _nm_register_setting (OVS_PATCH, NM_SETTING_PRIORITY_HW_BASE)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PATCH) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_patch_get_peer: + * @self: the #NMSettingOvsPatch + * + * Returns: the #NMSettingOvsPatch:peer property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_patch_get_peer (NMSettingOvsPatch *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PATCH (self), NULL); + + return self->peer; +} + +/*****************************************************************************/ + +static int +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH (setting); + int family = AF_UNSPEC; + + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + + if (!self->peer) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_OVS_PATCH_SETTING_NAME, + NM_SETTING_OVS_PATCH_PEER); + return FALSE; + } + + if (nm_utils_ipaddr_valid (AF_INET, self->peer)) + family = AF_INET; + else if (nm_utils_ipaddr_valid (AF_INET6, self->peer)) + family = AF_INET6; + else { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP address"), + self->peer); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_OVS_PATCH_SETTING_NAME, + NM_SETTING_OVS_PATCH_PEER); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH (object); + + switch (prop_id) { + case PROP_PEER: + g_value_set_string (value, self->peer); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH (object); + + switch (prop_id) { + case PROP_PEER: + g_free (self->peer); + self->peer = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_patch_init (NMSettingOvsPatch *self) +{ +} + +/** + * nm_setting_ovs_patch_new: + * + * Creates a new #NMSettingOvsPatch object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsPatch object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_patch_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_OVS_PATCH, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingOvsPatch *self = NM_SETTING_OVS_PATCH (object); + + g_free (self->peer); + + G_OBJECT_CLASS (nm_setting_ovs_patch_parent_class)->finalize (object); +} + +static void +nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /** + * NMSettingOvsPatch:peer: + * + * Specifies the unicast destination IP address of a remote OpenVSwitch + * bridge port to connect to. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_PEER, + g_param_spec_string (NM_SETTING_OVS_PATCH_PEER, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-ovs-patch.h b/libnm-core/nm-setting-ovs-patch.h new file mode 100644 index 00000000..091f0d43 --- /dev/null +++ b/libnm-core/nm-setting-ovs-patch.h @@ -0,0 +1,54 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_PATCH_H__ +#define __NM_SETTING_OVS_PATCH_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_PATCH (nm_setting_ovs_patch_get_type ()) +#define NM_SETTING_OVS_PATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatch)) +#define NM_SETTING_OVS_PATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OVS_PATCHCONFIG, NMSettingOvsPatchClass)) +#define NM_IS_SETTING_OVS_PATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OVS_PATCH)) +#define NM_IS_SETTING_OVS_PATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_OVS_PATCH)) +#define NM_SETTING_OVS_PATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OVS_PATCH, NMSettingOvsPatchClass)) + +#define NM_SETTING_OVS_PATCH_SETTING_NAME "ovs-patch" + +#define NM_SETTING_OVS_PATCH_PEER "peer" + +typedef struct _NMSettingOvsPatchClass NMSettingOvsPatchClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_patch_get_type (void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_patch_new (void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_patch_get_peer (NMSettingOvsPatch *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_PATCH_H__ */ diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c new file mode 100644 index 00000000..bd05f2e7 --- /dev/null +++ b/libnm-core/nm-setting-ovs-port.c @@ -0,0 +1,471 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-ovs-port.h" + +#include "nm-connection-private.h" +#include "nm-setting-connection.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-ovs-port + * @short_description: Describes connection properties for OpenVSwitch ports. + * + * The #NMSettingOvsPort object is a #NMSetting subclass that describes properties + * necessary for OpenVSwitch ports. + **/ + +enum { + PROP_0, + PROP_VLAN_MODE, + PROP_TAG, + PROP_LACP, + PROP_BOND_MODE, + PROP_BOND_UPDELAY, + PROP_BOND_DOWNDELAY, + LAST_PROP +}; + +/** + * NMSettingOvsPort: + * + * OvsPort Link Settings + */ +struct _NMSettingOvsPort { + NMSetting parent; + + char *vlan_mode; + guint tag; + char *lacp; + char *bond_mode; + guint bond_updelay; + guint bond_downdelay; +}; + +struct _NMSettingOvsPortClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING, + _nm_register_setting (OVS_PORT, NM_SETTING_PRIORITY_HW_BASE)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PORT) + +/*****************************************************************************/ + +/** + * nm_setting_ovs_port_get_vlan_mode: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:vlan-mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_vlan_mode (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), NULL); + + return self->vlan_mode; +} + +/** + * nm_setting_ovs_port_get_tag: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:tag property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_tag (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), 0); + + return self->tag; +} + +/** + * nm_setting_ovs_port_get_lacp: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:lacp property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_lacp (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), NULL); + + return self->lacp; +} + +/** + * nm_setting_ovs_port_get_bond_mode: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-mode property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_ovs_port_get_bond_mode (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), NULL); + + return self->bond_mode; +} + +/** + * nm_setting_ovs_port_get_bond_updelay: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-updelay property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_bond_updelay (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), 0); + + return self->bond_updelay; +} + +/** + * nm_setting_ovs_port_get_bond_downdelay: + * @self: the #NMSettingOvsPort + * + * Returns: the #NMSettingOvsPort:bond-downdelay property of the setting + * + * Since: 1.10 + **/ +guint +nm_setting_ovs_port_get_bond_downdelay (NMSettingOvsPort *self) +{ + g_return_val_if_fail (NM_IS_SETTING_OVS_PORT (self), 0); + + return self->bond_downdelay; +} + +/*****************************************************************************/ + +static int +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT (setting); + + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + + if (connection) { + NMSettingConnection *s_con; + const char *slave_type; + + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_SETTING, + _("missing setting")); + g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME); + return FALSE; + } + + if (!nm_setting_connection_get_master (s_con)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have a master."), + NM_SETTING_OVS_PORT_SETTING_NAME); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER); + return FALSE; + } + + slave_type = nm_setting_connection_get_slave_type (s_con); + if ( slave_type + && strcmp (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("A connection with a '%s' setting must have the slave-type set to '%s'. Instead it is '%s'"), + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + slave_type); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE); + return FALSE; + } + } + + if (!NM_IN_STRSET (self->vlan_mode, "access", "native-tagged", "native-untagged", "trunk", NULL)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in vlan_mode"), + self->vlan_mode); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_VLAN_MODE); + return FALSE; + } + + if (self->tag >= 4095) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("the tag id must be in range 0-4094 but is %u"), + self->tag); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_TAG); + return FALSE; + } + + if (!NM_IN_STRSET (self->lacp, "active", "off", "passive", NULL)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in lacp"), + self->lacp); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_LACP); + return FALSE; + } + + if (!NM_IN_STRSET (self->bond_mode, "active-backup", "balance-slb", "balance-tcp", NULL)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not allowed in bond_mode"), + self->bond_mode); + g_prefix_error (error, "%s.%s: ", NM_SETTING_OVS_PORT_SETTING_NAME, NM_SETTING_OVS_PORT_BOND_MODE); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT (object); + + switch (prop_id) { + case PROP_VLAN_MODE: + g_value_set_string (value, self->vlan_mode); + break; + case PROP_TAG: + g_value_set_uint (value, self->tag); + break; + case PROP_LACP: + g_value_set_string (value, self->lacp); + break; + case PROP_BOND_MODE: + g_value_set_string (value, self->bond_mode); + break; + case PROP_BOND_UPDELAY: + g_value_set_uint (value, self->bond_updelay); + break; + case PROP_BOND_DOWNDELAY: + g_value_set_uint (value, self->bond_downdelay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT (object); + + switch (prop_id) { + case PROP_VLAN_MODE: + g_free (self->vlan_mode); + self->vlan_mode = g_value_dup_string (value); + break; + case PROP_TAG: + self->tag = g_value_get_uint (value); + break; + case PROP_LACP: + g_free (self->lacp); + self->lacp = g_value_dup_string (value); + break; + case PROP_BOND_MODE: + g_free (self->bond_mode); + self->bond_mode = g_value_dup_string (value); + break; + case PROP_BOND_UPDELAY: + self->bond_updelay = g_value_get_uint (value); + break; + case PROP_BOND_DOWNDELAY: + self->bond_downdelay = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_ovs_port_init (NMSettingOvsPort *self) +{ +} + +/** + * nm_setting_ovs_port_new: + * + * Creates a new #NMSettingOvsPort object with default values. + * + * Returns: (transfer full): the new empty #NMSettingOvsPort object + * + * Since: 1.10 + **/ +NMSetting * +nm_setting_ovs_port_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_OVS_PORT, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingOvsPort *self = NM_SETTING_OVS_PORT (object); + + g_free (self->vlan_mode); + g_free (self->lacp); + g_free (self->bond_mode); + + G_OBJECT_CLASS (nm_setting_ovs_port_parent_class)->finalize (object); +} + +static void +nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /** + * NMSettingOvsPort:vlan-mode: + * + * The VLAN mode. One of "access", "native-tagged", "native-untagged", + * "trunk" or unset. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_VLAN_MODE, + g_param_spec_string (NM_SETTING_OVS_PORT_VLAN_MODE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsPort:tag: + * + * The VLAN tag in the range 0-4095. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_TAG, + g_param_spec_uint (NM_SETTING_OVS_PORT_TAG, "", "", + 0, 4095, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsPort:lacp: + * + * LACP mode. One of "active", "off", or "passive". + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_LACP, + g_param_spec_string (NM_SETTING_OVS_PORT_LACP, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsPort:bond-mode: + * + * Bonding mode. One of "active-backup", "balance-slb", or "balance-tcp". + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_BOND_MODE, + g_param_spec_string (NM_SETTING_OVS_PORT_BOND_MODE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + + /** + * NMSettingOvsPort:bond-updelay: + * + * The time port must be active befor it starts forwarding traffic. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_BOND_UPDELAY, + g_param_spec_uint (NM_SETTING_OVS_PORT_BOND_UPDELAY, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingOvsPort:bond-downdelay: + * + * The time port must be inactive in order to be considered down. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_BOND_DOWNDELAY, + g_param_spec_uint (NM_SETTING_OVS_PORT_BOND_DOWNDELAY, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-ovs-port.h b/libnm-core/nm-setting-ovs-port.h new file mode 100644 index 00000000..4c14f123 --- /dev/null +++ b/libnm-core/nm-setting-ovs-port.h @@ -0,0 +1,69 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2017 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_OVS_PORT_H__ +#define __NM_SETTING_OVS_PORT_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_OVS_PORT (nm_setting_ovs_port_get_type ()) +#define NM_SETTING_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPort)) +#define NM_SETTING_OVS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OVS_PORTCONFIG, NMSettingOvsPortClass)) +#define NM_IS_SETTING_OVS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OVS_PORT)) +#define NM_IS_SETTING_OVS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_OVS_PORT)) +#define NM_SETTING_OVS_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OVS_PORT, NMSettingOvsPortClass)) + +#define NM_SETTING_OVS_PORT_SETTING_NAME "ovs-port" + +#define NM_SETTING_OVS_PORT_VLAN_MODE "vlan-mode" +#define NM_SETTING_OVS_PORT_TAG "tag" +#define NM_SETTING_OVS_PORT_LACP "lacp" +#define NM_SETTING_OVS_PORT_BOND_MODE "bond-mode" +#define NM_SETTING_OVS_PORT_BOND_UPDELAY "bond-updelay" +#define NM_SETTING_OVS_PORT_BOND_DOWNDELAY "bond-downdelay" + +typedef struct _NMSettingOvsPortClass NMSettingOvsPortClass; + +NM_AVAILABLE_IN_1_10 +GType nm_setting_ovs_port_get_type (void); +NM_AVAILABLE_IN_1_10 +NMSetting *nm_setting_ovs_port_new (void); + +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_vlan_mode (NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_tag (NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_lacp (NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +const char *nm_setting_ovs_port_get_bond_mode (NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_bond_updelay (NMSettingOvsPort *self); +NM_AVAILABLE_IN_1_10 +guint nm_setting_ovs_port_get_bond_downdelay (NMSettingOvsPort *self); + +G_END_DECLS + +#endif /* __NM_SETTING_OVS_PORT_H__ */ diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c index 3519117c..32900c84 100644 --- a/libnm-core/nm-setting-ppp.c +++ b/libnm-core/nm-setting-ppp.c @@ -36,7 +36,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING, - _nm_register_setting (PPP, 3)) + _nm_register_setting (PPP, NM_SETTING_PRIORITY_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPP) #define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate)) @@ -663,7 +663,7 @@ nm_setting_ppp_class_init (NMSettingPppClass *setting_class) /** * NMSettingPpp:require-mppe: * - * If %TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for + * If %TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for * the PPP session. If either 64-bit or 128-bit MPPE is not available the * session will fail. Note that MPPE is not used on mobile broadband * connections. @@ -679,7 +679,7 @@ nm_setting_ppp_class_init (NMSettingPppClass *setting_class) /** * NMSettingPpp:require-mppe-128: * - * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be + * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be * required for the PPP session, and the "require-mppe" property must also * be set to %TRUE. If 128-bit MPPE is not available the session will fail. **/ diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c index c7fbd56d..d7a1a0db 100644 --- a/libnm-core/nm-setting-pppoe.c +++ b/libnm-core/nm-setting-pppoe.c @@ -39,12 +39,13 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING, - _nm_register_setting (PPPOE, 3)) + _nm_register_setting (PPPOE, NM_SETTING_PRIORITY_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPPOE) #define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate)) typedef struct { + char *parent; char *service; char *username; char *password; @@ -53,6 +54,7 @@ typedef struct { enum { PROP_0, + PROP_PARENT, PROP_SERVICE, PROP_USERNAME, PROP_PASSWORD, @@ -75,6 +77,22 @@ nm_setting_pppoe_new (void) } /** + * nm_setting_pppoe_get_parent: + * @setting: the #NMSettingPppoe + * + * Returns: the #NMSettingPppoe:parent property of the setting + * + * Since: 1.10 + **/ +const char * +nm_setting_pppoe_get_parent (NMSettingPppoe *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL); + + return NM_SETTING_PPPOE_GET_PRIVATE (setting)->parent; +} + +/** * nm_setting_pppoe_get_service: * @setting: the #NMSettingPppoe * @@ -134,6 +152,7 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting); + gs_free_error GError *local_error = NULL; if (!priv->username) { g_set_error_literal (error, @@ -160,6 +179,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( priv->parent + && !nm_utils_is_valid_iface_name (priv->parent, &local_error)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "'%s': %s", priv->parent, local_error->message); + g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_PARENT); + return FALSE; + } + return TRUE; } @@ -192,6 +221,10 @@ set_property (GObject *object, guint prop_id, NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object); switch (prop_id) { + case PROP_PARENT: + g_free (priv->parent); + priv->parent = g_value_dup_string (value); + break; case PROP_SERVICE: g_free (priv->service); priv->service = g_value_dup_string (value); @@ -220,6 +253,9 @@ get_property (GObject *object, guint prop_id, NMSettingPppoe *setting = NM_SETTING_PPPOE (object); switch (prop_id) { + case PROP_PARENT: + g_value_set_string (value, nm_setting_pppoe_get_parent (setting)); + break; case PROP_SERVICE: g_value_set_string (value, nm_setting_pppoe_get_service (setting)); break; @@ -243,6 +279,7 @@ finalize (GObject *object) { NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object); + g_free (priv->parent); g_free (priv->username); g_free (priv->password); g_free (priv->service); @@ -267,6 +304,25 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class) /* Properties */ /** + * NMSettingPppoe:parent: + * + * If given, specifies the parent interface name on which this PPPoE + * connection should be created. If this property is not specified, + * the connection is activated on the interface specified in + * #NMSettingConnection:interface-name of #NMSettingConnection. + * + * Since: 1.10 + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_string (NM_SETTING_PPPOE_PARENT, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** * NMSettingPppoe:service: * * If specified, instruct PPPoE to only initiate sessions with access diff --git a/libnm-core/nm-setting-pppoe.h b/libnm-core/nm-setting-pppoe.h index b6717cde..cab96e3b 100644 --- a/libnm-core/nm-setting-pppoe.h +++ b/libnm-core/nm-setting-pppoe.h @@ -40,6 +40,7 @@ G_BEGIN_DECLS #define NM_SETTING_PPPOE_SETTING_NAME "pppoe" +#define NM_SETTING_PPPOE_PARENT "parent" #define NM_SETTING_PPPOE_SERVICE "service" #define NM_SETTING_PPPOE_USERNAME "username" #define NM_SETTING_PPPOE_PASSWORD "password" @@ -64,6 +65,8 @@ typedef struct { GType nm_setting_pppoe_get_type (void); NMSetting *nm_setting_pppoe_new (void); +NM_AVAILABLE_IN_1_10 +const char *nm_setting_pppoe_get_parent (NMSettingPppoe *setting); const char *nm_setting_pppoe_get_service (NMSettingPppoe *setting); const char *nm_setting_pppoe_get_username (NMSettingPppoe *setting); const char *nm_setting_pppoe_get_password (NMSettingPppoe *setting); diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index 79b6ac87..30e2a160 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -27,17 +27,17 @@ #include "nm-core-internal.h" -void _nm_register_setting (const char *name, - const GType type, - const guint32 priority); +void _nm_register_setting_impl (const char *name, + GType type, + NMSettingPriority priority); #define _nm_register_setting(name, priority) \ G_STMT_START { \ - _nm_register_setting (NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \ + _nm_register_setting_impl ("" NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \ } G_STMT_END -gboolean _nm_setting_is_base_type (NMSetting *setting); -gboolean _nm_setting_type_is_base_type (GType type); +NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting); +NMSettingPriority _nm_setting_type_get_base_type_priority (GType type); gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); typedef enum NMSettingUpdateSecretResult { diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c index 1492892c..58a22080 100644 --- a/libnm-core/nm-setting-proxy.c +++ b/libnm-core/nm-setting-proxy.c @@ -40,7 +40,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING, - _nm_register_setting (PROXY, 4)) + _nm_register_setting (PROXY, NM_SETTING_PRIORITY_IP)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PROXY) #define NM_SETTING_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate)) diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c index fd251b7d..e0da89aa 100644 --- a/libnm-core/nm-setting-serial.c +++ b/libnm-core/nm-setting-serial.c @@ -38,7 +38,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING, - _nm_register_setting (SERIAL, 2)) + _nm_register_setting (SERIAL, NM_SETTING_PRIORITY_HW_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_SERIAL) #define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate)) diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index f64aa5f9..c0309665 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -40,7 +40,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING, - _nm_register_setting (TEAM_PORT, 3)) + _nm_register_setting (TEAM_PORT, NM_SETTING_PRIORITY_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM_PORT) #define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate)) diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index e83ce309..0a09c4a6 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -27,7 +27,6 @@ #include "nm-utils.h" #include "nm-utils-private.h" #include "nm-connection-private.h" -#include "nm-utils-private.h" /** * SECTION:nm-setting-team @@ -38,7 +37,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING, - _nm_register_setting (TEAM, 1)) + _nm_register_setting (TEAM, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM) #define NM_SETTING_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate)) diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c index 62e9ef14..dab407bd 100644 --- a/libnm-core/nm-setting-tun.c +++ b/libnm-core/nm-setting-tun.c @@ -39,7 +39,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING, - _nm_register_setting (TUN, 1)) + _nm_register_setting (TUN, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TUN) #define NM_SETTING_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate)) diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c index 71d73891..049607e1 100644 --- a/libnm-core/nm-setting-user.c +++ b/libnm-core/nm-setting-user.c @@ -64,7 +64,7 @@ struct _NMSettingUserClass { }; G_DEFINE_TYPE_WITH_CODE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING, - _nm_register_setting (USER, 10)) + _nm_register_setting (USER, NM_SETTING_PRIORITY_USER)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_USER) #define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER) @@ -597,6 +597,18 @@ nm_setting_user_class_init (NMSettingUserClass *klass) * * Since: 1.8 **/ + /* ---ifcfg-rh--- + * property: data + * variable: NM_USER_* + * description: each key/value pair is stored as a separate variable with + * name composed by concatenating NM_USER_ with the encoded key. The key is + * encoded by substituting lowercase letters with uppercase and prepending + * uppercase letters with an underscore. A dot is encoded as a double + * underscore. Remaining characters are encoded as underscore followed by a + * 3 digit octal representation of the character. + * example: NM_USER_FOO__BAR=something + * ---end--- + */ obj_properties[PROP_DATA] = g_param_spec_boxed (NM_SETTING_USER_DATA, "", "", G_TYPE_HASH_TABLE, diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index ab1c5465..f9c6e02d 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -42,7 +42,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING, - _nm_register_setting (VLAN, 1)) + _nm_register_setting (VLAN, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VLAN) #define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate)) diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index aa4ddc3a..6b42e0c7 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -44,7 +44,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING, - _nm_register_setting (VPN, 1)) + _nm_register_setting (VPN, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VPN) #define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate)) @@ -933,7 +933,7 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class) * * Timeout for the VPN service to establish the connection. Some services * may take quite a long time to connect. - * Value of 0 means a default timeout, which is 60 seconds (unless overriden + * Value of 0 means a default timeout, which is 60 seconds (unless overridden * by vpn.timeout in configuration file). Values greater than zero mean * timeout in seconds. * diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c index f6717a2f..4be6a236 100644 --- a/libnm-core/nm-setting-vxlan.c +++ b/libnm-core/nm-setting-vxlan.c @@ -37,7 +37,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING, - _nm_register_setting (VXLAN, 1)) + _nm_register_setting (VXLAN, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VXLAN) #define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) @@ -598,7 +598,7 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) /** * NMSettingVxlan:id: * - * Specifies the VXLAN Network Identifer (or VXLAN Segment Identifier) to + * Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to * use. * * Since: 1.2 diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c index f893cbdc..dbfb46e4 100644 --- a/libnm-core/nm-setting-wimax.c +++ b/libnm-core/nm-setting-wimax.c @@ -43,7 +43,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING, - _nm_register_setting (WIMAX, 1)) + _nm_register_setting (WIMAX, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIMAX) #define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c index 5476e357..9d255e1d 100644 --- a/libnm-core/nm-setting-wired.c +++ b/libnm-core/nm-setting-wired.c @@ -41,7 +41,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING, - _nm_register_setting (WIRED, 1)) + _nm_register_setting (WIRED, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRED) #define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate)) @@ -1012,9 +1012,9 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) /** * NMSettingWired:port: * - * Specific port type to use if multiple the device supports multiple + * Specific port type to use if the device supports multiple * attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit - * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface. + * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface). * If the device supports only one port type, this setting is ignored. **/ /* ---ifcfg-rh--- @@ -1033,7 +1033,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) /** * NMSettingWired:speed: * - * Can be set to a value grater than zero only when "auto-negotiate" is "off". + * Can be set to a value greater than zero only when "auto-negotiate" is "off". * In that case, statically configures the device to use that specified speed. * In Mbit/s, ie 100 == 100Mbit/s. * Must be set together with the "duplex" property when non-zero. @@ -1147,7 +1147,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) * If specified, request that the device use this MAC address instead. * This is known as MAC cloning or spoofing. * - * Beside explicitly specifing a MAC address, the special values "preserve", "permanent", + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", * "random" and "stable" are supported. * "preserve" means not to touch the MAC address on activation. * "permanent" means to use the permanent hardware address if the device @@ -1243,7 +1243,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class) * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled * globally-administered, burned-in MAC address. * - * If the value contains more then one additional MAC addresses, one of + * If the value contains more than one additional MAC addresses, one of * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" * will create a fully scrambled MAC address, randomly locally or globally * administered. diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c index 70bdf754..91bcbe7a 100644 --- a/libnm-core/nm-setting-wireless-security.c +++ b/libnm-core/nm-setting-wireless-security.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2007 - 2017 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -54,7 +54,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS_SECURITY, 2)) + _nm_register_setting (WIRELESS_SECURITY, NM_SETTING_PRIORITY_HW_AUX)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS_SECURITY) #define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate)) @@ -65,6 +65,7 @@ typedef struct { GSList *proto; /* GSList of strings */ GSList *pairwise; /* GSList of strings */ GSList *group; /* GSList of strings */ + NMSettingWirelessSecurityPmf pmf; /* LEAP */ char *leap_username; @@ -83,6 +84,9 @@ typedef struct { /* WPA-PSK */ char *psk; NMSettingSecretFlags psk_flags; + + /* WPS */ + NMSettingWirelessSecurityWpsMethod wps_method; } NMSettingWirelessSecurityPrivate; enum { @@ -93,6 +97,7 @@ enum { PROP_PROTO, PROP_PAIRWISE, PROP_GROUP, + PROP_PMF, PROP_LEAP_USERNAME, PROP_WEP_KEY0, PROP_WEP_KEY1, @@ -104,6 +109,7 @@ enum { PROP_PSK_FLAGS, PROP_LEAP_PASSWORD, PROP_LEAP_PASSWORD_FLAGS, + PROP_WPS_METHOD, LAST_PROP }; @@ -573,6 +579,22 @@ nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting) g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP); } +/* + * nm_setting_wireless_security_get_pmf: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:pmf property of the setting + * + * Since: 1.10 + **/ +NMSettingWirelessSecurityPmf +nm_setting_wireless_security_get_pmf (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->pmf; +} + /** * nm_setting_wireless_security_get_psk: * @setting: the #NMSettingWirelessSecurity @@ -775,6 +797,23 @@ nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *settin return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_type; } +/** + * nm_setting_wireless_security_get_wps_method: + * @setting: the #NMSettingWirelessSecurity + * + * Returns: the #NMSettingWirelessSecurity:wps-method property of the setting + * + * Since: 1.10 + **/ +NMSettingWirelessSecurityWpsMethod +nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED); + + return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wps_method; +} + static GPtrArray * need_secrets (NMSetting *setting) { @@ -1013,6 +1052,50 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } + G_STATIC_ASSERT_EXPR (((NMSettingWirelessSecurityPmf) -1) > 0); + if (priv->pmf > NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PMF); + return FALSE; + } + + if ( NM_IN_SET (priv->pmf, + NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL, + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + && !NM_IN_STRSET (priv->key_mgmt, "wpa-eap", "wpa-psk")) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' can only be used with '%s=%s' or '%s=%s'"), + priv->pmf == NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL ? "optional" : "required", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk"); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PMF); + return FALSE; + } + + /* WPS */ + if (priv->wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD); + return FALSE; + } + + if (priv->wps_method & NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED && priv->wps_method != NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't be simultaneously disabled and enabled")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD); + return FALSE; + } + return TRUE; } @@ -1198,6 +1281,9 @@ set_property (GObject *object, guint prop_id, g_slist_free_full (priv->group, g_free); priv->group = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE); break; + case PROP_PMF: + priv->pmf = g_value_get_int (value); + break; case PROP_LEAP_USERNAME: g_free (priv->leap_username); priv->leap_username = g_value_dup_string (value); @@ -1238,6 +1324,9 @@ set_property (GObject *object, guint prop_id, case PROP_WEP_KEY_TYPE: priv->wep_key_type = g_value_get_enum (value); break; + case PROP_WPS_METHOD: + priv->wps_method = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1270,6 +1359,9 @@ get_property (GObject *object, guint prop_id, case PROP_GROUP: g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->group, TRUE)); break; + case PROP_PMF: + g_value_set_int (value, nm_setting_wireless_security_get_pmf (setting)); + break; case PROP_LEAP_USERNAME: g_value_set_string (value, priv->leap_username); break; @@ -1303,6 +1395,9 @@ get_property (GObject *object, guint prop_id, case PROP_WEP_KEY_TYPE: g_value_set_enum (value, priv->wep_key_type); break; + case PROP_WPS_METHOD: + g_value_set_uint (value, priv->wps_method); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1468,6 +1563,37 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_PARAM_STATIC_STRINGS)); /** + * NMSettingWirelessSecurity:pmf: + * + * Indicates whether Protected Management Frames (802.11w) must be enabled + * for the connection. One of %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT + * (use global default value), %NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE + * (disable PMF), %NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (enable PMF if + * the supplicant and the access point support it) or + * %NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (enable PMF and fail if not + * supported). When set to %NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT and no + * global default is set, PMF will be optionally enabled. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: pmf + * variable: PMF(+) + * values: default, disable, optional, required + * description: Enables or disables PMF (802.11w) + * example: PMF=required + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_PMF, + g_param_spec_int (NM_SETTING_WIRELESS_SECURITY_PMF, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); + + /** * NMSettingWirelessSecurity:leap-username: * * The login username for legacy LEAP connections (ie, key-mgmt = @@ -1708,4 +1834,34 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting G_VARIANT_TYPE_UINT32, wep_key_type_to_dbus, NULL); + /** + * NMSettingWirelessSecurity:wps-method: + * + * Flags indicating which mode of WPS is to be used if any. + * + * There's little point in changing the default setting as NetworkManager will + * automatically determine whether it's feasible to start WPS enrollment from + * the Access Point capabilities. + * + * WPS can be disabled by setting this property to a value of 1. + * + * Since: 1.10 + **/ + /* ---ifcfg-rh--- + * property: wps-method + * variable: WPS_METHOD + * description: Used to control the WPS methods to be used + * Valid values are "default", "auto", "disabled", "pin" and "pbc". + * If omitted, whatver the AP announces is used. + * example: WPS_METHOD=disabled, WPS_METHOD="pin pbc" + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_WPS_METHOD, + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, "", "", + 0, G_MAXUINT32, NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h index ae252f11..e7641b31 100644 --- a/libnm-core/nm-setting-wireless-security.h +++ b/libnm-core/nm-setting-wireless-security.h @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2007 - 2017 Red Hat, Inc. * Copyright 2007 - 2008 Novell, Inc. */ @@ -68,15 +68,54 @@ typedef enum { NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */ NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */ - NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE + NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE, /*< skip >*/ } NMWepKeyType; +/** + * NMSettingWirelessSecurityPmf: + * @NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT: use the default value + * @NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE: disable PMF + * @NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL: enable PMF if the supplicant and the AP support it + * @NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED: require PMF and fail if not available + * + * These flags indicate whether PMF must be enabled. + **/ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT = 0, + NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE = 1, + NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL = 2, + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED = 3, + _NM_SETTING_WIRELESS_SECURITY_PMF_NUM, /*< skip >*/ + NM_SETTING_WIRELESS_SECURITY_PMF_LAST = _NM_SETTING_WIRELESS_SECURITY_PMF_NUM - 1, /*< skip >*/ +} NMSettingWirelessSecurityPmf; + +/** + * NMSettingWirelessSecurityWpsMethod: + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT: Attempt whichever method AP supports + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED: WPS can not be used. + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO: Use WPS, any method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC: use WPS push-buthon method + * @NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN: use PIN method + * + * Configure the use of WPS by a connection while it activates. + * + * Since: 1.10 + **/ +typedef enum { + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT = 0x00000000, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED = 0x00000001, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_AUTO = 0x00000002, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PBC = 0x00000004, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN = 0x00000008, +} NMSettingWirelessSecurityWpsMethod; + #define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt" #define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx" #define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg" #define NM_SETTING_WIRELESS_SECURITY_PROTO "proto" #define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise" #define NM_SETTING_WIRELESS_SECURITY_GROUP "group" +#define NM_SETTING_WIRELESS_SECURITY_PMF "pmf" #define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username" #define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0" #define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1" @@ -88,6 +127,7 @@ typedef enum { #define NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS "psk-flags" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password" #define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags" +#define NM_SETTING_WIRELESS_SECURITY_WPS_METHOD "wps-method" /** * NMSettingWirelessSecurity: @@ -132,6 +172,9 @@ void nm_setting_wireless_security_remove_group (NMSettingWireles gboolean nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting, const char *group); void nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting); +NM_AVAILABLE_IN_1_10 +NMSettingWirelessSecurityPmf nm_setting_wireless_security_get_pmf (NMSettingWirelessSecurity *setting); + const char *nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting); NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags (NMSettingWirelessSecurity *setting); @@ -147,6 +190,9 @@ const char *nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSec NMSettingSecretFlags nm_setting_wireless_security_get_wep_key_flags (NMSettingWirelessSecurity *setting); NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting); +NM_AVAILABLE_IN_1_10 +NMSettingWirelessSecurityWpsMethod nm_setting_wireless_security_get_wps_method (NMSettingWirelessSecurity *setting); + G_END_DECLS #endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */ diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index 8ae84d4c..0a3915bf 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -41,7 +41,7 @@ **/ G_DEFINE_TYPE_WITH_CODE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING, - _nm_register_setting (WIRELESS, 1)) + _nm_register_setting (WIRELESS, NM_SETTING_PRIORITY_HW_BASE)) NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS) #define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate)) @@ -1353,7 +1353,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * If specified, request that the device use this MAC address instead. * This is known as MAC cloning or spoofing. * - * Beside explicitly specifing a MAC address, the special values "preserve", "permanent", + * Beside explicitly specifying a MAC address, the special values "preserve", "permanent", * "random" and "stable" are supported. * "preserve" means not to touch the MAC address on activation. * "permanent" means to use the permanent hardware address of the device. @@ -1447,7 +1447,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class) * "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled * globally-administered, burned-in MAC address. * - * If the value contains more then one additional MAC addresses, one of + * If the value contains more than one additional MAC addresses, one of * them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00" * will create a fully scrambled MAC address, randomly locally or globally * administered. diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index e4be8706..9c8e53ae 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -60,7 +60,7 @@ G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) typedef struct { const char *name; GType type; - guint32 priority; + NMSettingPriority priority; } SettingInfo; typedef struct { @@ -118,61 +118,31 @@ _ensure_registered_constructor (void) /*****************************************************************************/ /* - * _nm_register_setting: + * _nm_register_setting_impl: * @name: the name of the #NMSetting object to register * @type: the #GType of the #NMSetting - * @priority: the sort priority of the setting, see below + * @priority: the sort priority of the setting, see #NMSettingPriority * * INTERNAL ONLY: registers a setting's internal properties with libnm. - * - * A setting's priority should roughly follow the OSI layer model, but it also - * controls which settings get asked for secrets first. Thus settings which - * relate to things that must be working first, like hardware, should get a - * higher priority than things which layer on top of the hardware. For example, - * the GSM/CDMA settings should provide secrets before the PPP setting does, - * because a PIN is required to unlock the device before PPP can even start. - * Even settings without secrets should be assigned the right priority. - * - * 0: reserved for the Connection setting - * - * 1: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. - * These priority 1 settings are also "base types", which means that at least - * one of them is required for the connection to be valid, and their name is - * valid in the 'type' property of the Connection setting. - * - * 2: hardware-related auxiliary settings that require a base setting to be - * successful first, like Wi-Fi security, 802.1x, etc. - * - * 3: hardware-independent settings that are required before IP connectivity - * can be established, like PPP, PPPoE, etc. - * - * 4: IP-level stuff - * - * 10: NMSettingUser */ void -(_nm_register_setting) (const char *name, - const GType type, - const guint32 priority) +_nm_register_setting_impl (const char *name, + GType type, + NMSettingPriority priority) { SettingInfo *info; - g_return_if_fail (name != NULL && *name); - g_return_if_fail (type != G_TYPE_INVALID); - g_return_if_fail (type != G_TYPE_NONE); + nm_assert (name && *name); + nm_assert (!NM_IN_SET (type, G_TYPE_INVALID, G_TYPE_NONE)); + nm_assert (priority != NM_SETTING_PRIORITY_INVALID); _ensure_registered (); - if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) { - g_return_if_fail (info->type == type); - g_return_if_fail (info->priority == priority); - g_return_if_fail (g_strcmp0 (info->name, name) == 0); - return; - } - g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL); + nm_assert (!g_hash_table_lookup (registered_settings, name)); + nm_assert (!g_hash_table_lookup (registered_settings_by_type, &type)); - if (priority == 0) - g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME); + nm_assert ( priority != NM_SETTING_PRIORITY_CONNECTION + || nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME)); info = g_slice_new0 (SettingInfo); info->type = type; @@ -189,7 +159,7 @@ _nm_setting_lookup_setting_by_type (GType type) return g_hash_table_lookup (registered_settings_by_type, &type); } -static guint32 +static NMSettingPriority _get_setting_type_priority (GType type) { const SettingInfo *info; @@ -200,7 +170,7 @@ _get_setting_type_priority (GType type) return info->priority; } -guint32 +NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting) { NMSettingPrivate *priv; @@ -211,21 +181,30 @@ _nm_setting_get_setting_priority (NMSetting *setting) return priv->info->priority; } -gboolean -_nm_setting_type_is_base_type (GType type) +NMSettingPriority +_nm_setting_type_get_base_type_priority (GType type) { + NMSettingPriority priority; + /* Historical oddity: PPPoE is a base-type even though it's not * priority 1. It needs to be sorted *after* lower-level stuff like * Wi-Fi security or 802.1x for secrets, but it's still allowed as a * base type. */ - return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE); + priority = _get_setting_type_priority (type); + if ( NM_IN_SET (priority, + NM_SETTING_PRIORITY_HW_BASE, + NM_SETTING_PRIORITY_HW_NON_BASE) + || type == NM_TYPE_SETTING_PPPOE) + return priority; + else + return NM_SETTING_PRIORITY_INVALID; } -gboolean -_nm_setting_is_base_type (NMSetting *setting) +NMSettingPriority +_nm_setting_get_base_type_priority (NMSetting *setting) { - return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting)); + return _nm_setting_type_get_base_type_priority (G_OBJECT_TYPE (setting)); } /** @@ -240,9 +219,9 @@ _nm_setting_is_base_type (NMSetting *setting) GType nm_setting_lookup_type (const char *name) { - SettingInfo *info; + const SettingInfo *info; - g_return_val_if_fail (name != NULL, G_TYPE_INVALID); + g_return_val_if_fail (name, G_TYPE_INVALID); _ensure_registered (); @@ -253,7 +232,7 @@ nm_setting_lookup_type (const char *name) gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b) { - guint32 prio_a, prio_b; + NMSettingPriority prio_a, prio_b; prio_a = _nm_setting_get_setting_priority ((NMSetting *) a); prio_b = _nm_setting_get_setting_priority ((NMSetting *) b); @@ -279,6 +258,10 @@ _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_t ; else if (!strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME; + else if (!strcmp (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) + port_type = NM_SETTING_OVS_PORT_SETTING_NAME; + else if (!strcmp (slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) + port_type = NM_SETTING_OVS_INTERFACE_SETTING_NAME; else if (!strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME)) port_type = NM_SETTING_TEAM_PORT_SETTING_NAME; else @@ -1343,6 +1326,8 @@ nm_setting_diff (NMSetting *a, NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; gboolean results_created = FALSE; + gboolean compared_any = FALSE; + gboolean diff_found = FALSE; g_return_val_if_fail (results != NULL, FALSE); g_return_val_if_fail (NM_IS_SETTING (a), FALSE); @@ -1391,6 +1376,8 @@ nm_setting_diff (NMSetting *a, if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) continue; + compared_any = TRUE; + if (b) { gboolean different; @@ -1439,6 +1426,7 @@ nm_setting_diff (NMSetting *a, if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { void *p; + diff_found = TRUE; if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { if ((r & GPOINTER_TO_UINT (p)) != r) g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); @@ -1448,13 +1436,28 @@ nm_setting_diff (NMSetting *a, } g_free (property_specs); - /* Don't return an empty hash table */ - if (results_created && !g_hash_table_size (*results)) { - g_hash_table_destroy (*results); - *results = NULL; + if (!compared_any && !b) { + /* special case: the setting has no properties, and the opposite + * setting @b is not given. The settings differ, and we signal that + * by returning an empty results hash. */ + diff_found = TRUE; } - return !(*results); + if (diff_found) { + /* if there is a difference, we always return FALSE. It also means, we might + * have allocated a new @results hash, and return if to the caller. */ + return FALSE; + } else { + if (results_created) { + /* the allocated hash is unused. Clear it again. */ + g_hash_table_destroy (*results); + *results = NULL; + } else { + /* we found no diff, and return false. However, the input + * @result is returned unmodified. */ + } + return TRUE; + } } #define CMP_AND_RETURN(n_a, n_b, name) \ diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 8a80d2d3..bc955834 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -32,11 +32,14 @@ #include <libintl.h> #include <gmodule.h> #include <sys/stat.h> +#include <net/if.h> #if WITH_JANSSON #include <jansson.h> #endif +#include "nm-utils/nm-enum-utils.h" +#include "nm-utils/nm-hash-utils.h" #include "nm-common-macros.h" #include "nm-utils-private.h" #include "nm-setting-private.h" @@ -58,85 +61,79 @@ * access points and devices, among other things. */ -struct EncodingTriplet -{ - const char *encoding1; - const char *encoding2; - const char *encoding3; -}; - struct IsoLangToEncodings { - const char * lang; - struct EncodingTriplet encodings; + const char *lang; + const char *const *encodings; }; +#define LANG_ENCODINGS(l, ...) { .lang = l, .encodings = (const char *[]) { __VA_ARGS__, NULL }} + /* 5-letter language codes */ static const struct IsoLangToEncodings isoLangEntries5[] = { /* Simplified Chinese */ - { "zh_cn", {"euc-cn", "gb2312", "gb18030"} }, /* PRC */ - { "zh_sg", {"euc-cn", "gb2312", "gb18030"} }, /* Singapore */ + LANG_ENCODINGS ("zh_cn", "euc-cn", "gb2312", "gb18030"), /* PRC */ + LANG_ENCODINGS ("zh_sg", "euc-cn", "gb2312", "gb18030"), /* Singapore */ /* Traditional Chinese */ - { "zh_tw", {"big5", "euc-tw", NULL} }, /* Taiwan */ - { "zh_hk", {"big5", "euc-tw", "big5-hkcs"} },/* Hong Kong */ - { "zh_mo", {"big5", "euc-tw", NULL} }, /* Macau */ + LANG_ENCODINGS ("zh_tw", "big5", "euc-tw"), /* Taiwan */ + LANG_ENCODINGS ("zh_hk", "big5", "euc-tw", "big5-hkcs"), /* Hong Kong */ + LANG_ENCODINGS ("zh_mo", "big5", "euc-tw"), /* Macau */ - /* Table end */ - { NULL, {NULL, NULL, NULL} } + LANG_ENCODINGS (NULL, NULL) }; /* 2-letter language codes; we don't care about the other 3 in this table */ static const struct IsoLangToEncodings isoLangEntries2[] = { /* Japanese */ - { "ja", {"euc-jp", "shift_jis", "iso-2022-jp"} }, + LANG_ENCODINGS ("ja", "euc-jp", "shift_jis", "iso-2022-jp"), /* Korean */ - { "ko", {"euc-kr", "iso-2022-kr", "johab"} }, + LANG_ENCODINGS ("ko", "euc-kr", "iso-2022-kr", "johab"), /* Thai */ - { "th", {"iso-8859-11","windows-874", NULL} }, + LANG_ENCODINGS ("th", "iso-8859-11", "windows-874"), /* Central European */ - { "hu", {"iso-8859-2", "windows-1250", NULL} }, /* Hungarian */ - { "cs", {"iso-8859-2", "windows-1250", NULL} }, /* Czech */ - { "hr", {"iso-8859-2", "windows-1250", NULL} }, /* Croatian */ - { "pl", {"iso-8859-2", "windows-1250", NULL} }, /* Polish */ - { "ro", {"iso-8859-2", "windows-1250", NULL} }, /* Romanian */ - { "sk", {"iso-8859-2", "windows-1250", NULL} }, /* Slovakian */ - { "sl", {"iso-8859-2", "windows-1250", NULL} }, /* Slovenian */ - { "sh", {"iso-8859-2", "windows-1250", NULL} }, /* Serbo-Croatian */ + LANG_ENCODINGS ("hu", "iso-8859-2", "windows-1250"), /* Hungarian */ + LANG_ENCODINGS ("cs", "iso-8859-2", "windows-1250"), /* Czech */ + LANG_ENCODINGS ("hr", "iso-8859-2", "windows-1250"), /* Croatian */ + LANG_ENCODINGS ("pl", "iso-8859-2", "windows-1250"), /* Polish */ + LANG_ENCODINGS ("ro", "iso-8859-2", "windows-1250"), /* Romanian */ + LANG_ENCODINGS ("sk", "iso-8859-2", "windows-1250"), /* Slovakian */ + LANG_ENCODINGS ("sl", "iso-8859-2", "windows-1250"), /* Slovenian */ + LANG_ENCODINGS ("sh", "iso-8859-2", "windows-1250"), /* Serbo-Croatian */ /* Cyrillic */ - { "ru", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Russian */ - { "be", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Belorussian */ - { "bg", {"windows-1251","koi8-r", "iso-8859-5"} }, /* Bulgarian */ - { "mk", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Macedonian */ - { "sr", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Serbian */ - { "uk", {"koi8-u", "koi8-r", "windows-1251"} }, /* Ukranian */ + LANG_ENCODINGS ("ru", "koi8-r", "windows-1251","iso-8859-5"), /* Russian */ + LANG_ENCODINGS ("be", "koi8-r", "windows-1251","iso-8859-5"), /* Belorussian */ + LANG_ENCODINGS ("bg", "windows-1251","koi8-r", "iso-8859-5"), /* Bulgarian */ + LANG_ENCODINGS ("mk", "koi8-r", "windows-1251", "iso-8859-5"),/* Macedonian */ + LANG_ENCODINGS ("sr", "koi8-r", "windows-1251", "iso-8859-5"),/* Serbian */ + LANG_ENCODINGS ("uk", "koi8-u", "koi8-r", "windows-1251"), /* Ukranian */ /* Arabic */ - { "ar", {"iso-8859-6", "windows-1256", NULL} }, + LANG_ENCODINGS ("ar", "iso-8859-6","windows-1256"), /* Baltic */ - { "et", {"iso-8859-4", "windows-1257", NULL} }, /* Estonian */ - { "lt", {"iso-8859-4", "windows-1257", NULL} }, /* Lithuanian */ - { "lv", {"iso-8859-4", "windows-1257", NULL} }, /* Latvian */ + LANG_ENCODINGS ("et", "iso-8859-4", "windows-1257"), /* Estonian */ + LANG_ENCODINGS ("lt", "iso-8859-4", "windows-1257"), /* Lithuanian */ + LANG_ENCODINGS ("lv", "iso-8859-4", "windows-1257"), /* Latvian */ /* Greek */ - { "el", {"iso-8859-7", "windows-1253", NULL} }, + LANG_ENCODINGS ("el", "iso-8859-7","windows-1253"), /* Hebrew */ - { "he", {"iso-8859-8", "windows-1255", NULL} }, - { "iw", {"iso-8859-8", "windows-1255", NULL} }, + LANG_ENCODINGS ("he", "iso-8859-8", "windows-1255"), + LANG_ENCODINGS ("iw", "iso-8859-8", "windows-1255"), /* Turkish */ - { "tr", {"iso-8859-9", "windows-1254", NULL} }, + LANG_ENCODINGS ("tr", "iso-8859-9", "windows-1254"), /* Table end */ - { NULL, {NULL, NULL, NULL} } + LANG_ENCODINGS (NULL, NULL) }; @@ -154,7 +151,7 @@ init_lang_to_encodings_hash (void) langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings5, (gpointer) enc->lang, - (gpointer) &enc->encodings); + (gpointer) enc->encodings); enc++; } } @@ -165,54 +162,73 @@ init_lang_to_encodings_hash (void) langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal); while (enc->lang) { g_hash_table_insert (langToEncodings2, (gpointer) enc->lang, - (gpointer) &enc->encodings); + (gpointer) enc->encodings); enc++; } } } - static gboolean -get_encodings_for_lang (const char *lang, - char **encoding1, - char **encoding2, - char **encoding3) +get_encodings_for_lang (const char *lang, const char *const **encodings) { - struct EncodingTriplet * encodings; - gboolean success = FALSE; - char * tmp_lang; - - g_return_val_if_fail (lang != NULL, FALSE); - g_return_val_if_fail (encoding1 != NULL, FALSE); - g_return_val_if_fail (encoding2 != NULL, FALSE); - g_return_val_if_fail (encoding3 != NULL, FALSE); + gs_free char *tmp_lang = NULL; - *encoding1 = "iso-8859-1"; - *encoding2 = "windows-1251"; - *encoding3 = NULL; + g_return_val_if_fail (lang, FALSE); + g_return_val_if_fail (encodings, FALSE); init_lang_to_encodings_hash (); - tmp_lang = g_strdup (lang); - if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang))) { - *encoding1 = (char *) encodings->encoding1; - *encoding2 = (char *) encodings->encoding2; - *encoding3 = (char *) encodings->encoding3; - success = TRUE; - } + if ((*encodings = g_hash_table_lookup (langToEncodings5, lang))) + return TRUE; /* Truncate tmp_lang to length of 2 */ - if (strlen (tmp_lang) > 2) + if (strlen (lang) > 2) { + tmp_lang = g_strdup (lang); tmp_lang[2] = '\0'; - if (!success && (encodings = g_hash_table_lookup (langToEncodings2, tmp_lang))) { - *encoding1 = (char *) encodings->encoding1; - *encoding2 = (char *) encodings->encoding2; - *encoding3 = (char *) encodings->encoding3; - success = TRUE; + if ((*encodings = g_hash_table_lookup (langToEncodings2, tmp_lang))) + return TRUE; + } + + return FALSE; +} + +static const char *const * +get_system_encodings (void) +{ + static const char *const *cached_encodings; + static char *default_encodings[4]; + const char *const *encodings = NULL; + char *lang; + + if (cached_encodings) + return cached_encodings; + + /* Use environment variables as encoding hint */ + lang = getenv ("LC_ALL"); + if (!lang) + lang = getenv ("LC_CTYPE"); + if (!lang) + lang = getenv ("LANG"); + if (lang) { + char *dot; + + lang = g_ascii_strdown (lang, -1); + if ((dot = strchr (lang, '.'))) + *dot = '\0'; + + get_encodings_for_lang (lang, &encodings); + g_free (lang); + } + if (!encodings) { + g_get_charset ((const char **) &default_encodings[0]); + default_encodings[1] = "iso-8859-1"; + default_encodings[2] = "windows-1251"; + default_encodings[3] = NULL; + encodings = (const char *const *) default_encodings; } - g_free (tmp_lang); - return success; + cached_encodings = encodings; + return cached_encodings; } /* init libnm */ @@ -281,37 +297,26 @@ gboolean _nm_utils_is_manager_process; char * nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) { + const char *const *encodings; + const char *const *e; char *converted = NULL; - char *lang, *e1 = NULL, *e2 = NULL, *e3 = NULL; g_return_val_if_fail (ssid != NULL, NULL); if (g_utf8_validate ((const gchar *) ssid, len, NULL)) return g_strndup ((const gchar *) ssid, len); - /* LANG may be a good encoding hint */ - g_get_charset ((const char **)(&e1)); - if ((lang = getenv ("LANG"))) { - char * dot; + encodings = get_system_encodings (); - lang = g_ascii_strdown (lang, -1); - if ((dot = strchr (lang, '.'))) - *dot = '\0'; - - get_encodings_for_lang (lang, &e1, &e2, &e3); - g_free (lang); + for (e = encodings; *e; e++) { + converted = g_convert ((const gchar *) ssid, len, "UTF-8", *e, NULL, NULL, NULL); + if (converted) + break; } - converted = g_convert ((const gchar *) ssid, len, "UTF-8", e1, NULL, NULL, NULL); - if (!converted && e2) - converted = g_convert ((const gchar *) ssid, len, "UTF-8", e2, NULL, NULL, NULL); - - if (!converted && e3) - converted = g_convert ((const gchar *) ssid, len, "UTF-8", e3, NULL, NULL, NULL); - if (!converted) { converted = g_convert_with_fallback ((const gchar *) ssid, len, - "UTF-8", e1, "?", NULL, NULL, NULL); + "UTF-8", encodings[0], "?", NULL, NULL, NULL); } if (!converted) { @@ -325,7 +330,7 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len) "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" "abcdefghijklmnopqrstuvwxyz{|}~"; - converted = g_strndup ((const gchar *)ssid, len); + converted = g_strndup ((const char *) ssid, len); g_strcanon (converted, valid_chars, '?'); } @@ -443,36 +448,6 @@ nm_utils_same_ssid (const guint8 *ssid1, gsize len1, return memcmp (ssid1, ssid2, len1) == 0 ? TRUE : FALSE; } -char ** -_nm_utils_strv_cleanup (char **strv, - gboolean strip_whitespace, - gboolean skip_empty, - gboolean skip_repeated) -{ - guint i, j; - - if (!strv || !*strv) - return strv; - - if (strip_whitespace) { - for (i = 0; strv[i]; i++) - g_strstrip (strv[i]); - } - if (!skip_empty && !skip_repeated) - return strv; - j = 0; - for (i = 0; strv[i]; i++) { - if ( (skip_empty && !*strv[i]) - || (skip_repeated && nm_utils_strv_find_first (strv, j, strv[i]) >= 0)) - g_free (strv[i]); - else - strv[j++] = strv[i]; - } - strv[j] = NULL; - return strv; -} - - gboolean _nm_utils_string_slist_validate (GSList *list, const char **valid_values) { @@ -1519,10 +1494,9 @@ nm_utils_ip4_netmask_to_prefix (guint32 netmask) guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix) { - return prefix < 32 ? ~htonl(0xFFFFFFFF >> prefix) : 0xFFFFFFFF; + return _nm_utils_ip4_prefix_to_netmask (prefix); } - /** * nm_utils_ip4_get_default_prefix: * @ip: an IPv4 address (in network byte order) @@ -1538,12 +1512,7 @@ nm_utils_ip4_prefix_to_netmask (guint32 prefix) guint32 nm_utils_ip4_get_default_prefix (guint32 ip) { - if (((ntohl (ip) & 0xFF000000) >> 24) <= 127) - return 8; /* Class A - 255.0.0.0 */ - else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191) - return 16; /* Class B - 255.255.0.0 */ - - return 24; /* Class C - 255.255.255.0 */ + return _nm_utils_ip4_get_default_prefix (ip); } /** @@ -1993,8 +1962,8 @@ nm_utils_ip_routes_to_variant (GPtrArray *routes) for (i = 0; i < routes->len; i++) { NMIPRoute *route = routes->pdata[i]; GVariantBuilder route_builder; - char **names; - int n; + gs_free const char **names = NULL; + guint j, len; g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&route_builder, "{sv}", @@ -2014,13 +1983,12 @@ nm_utils_ip_routes_to_variant (GPtrArray *routes) g_variant_new_uint32 ((guint32) nm_ip_route_get_metric (route))); } - names = nm_ip_route_get_attribute_names (route); - for (n = 0; names[n]; n++) { + names = _nm_ip_route_get_attribute_names (route, TRUE, &len); + for (j = 0; j < len; j++) { g_variant_builder_add (&route_builder, "{sv}", - names[n], - nm_ip_route_get_attribute (route, names[n])); + names[j], + nm_ip_route_get_attribute (route, names[j])); } - g_strfreev (names); g_variant_builder_add (&builder, "a{sv}", &route_builder); } @@ -3707,36 +3675,41 @@ _nm_utils_generate_mac_address_mask_parse (const char *value, gboolean nm_utils_is_valid_iface_name (const char *name, GError **error) { - g_return_val_if_fail (name != NULL, FALSE); + int i; - if (*name == '\0') { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is too short")); - return FALSE; - } + g_return_val_if_fail (name, FALSE); - if (strlen (name) >= 16) { + if (name[0] == '\0') { g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - _("interface name is longer than 15 characters")); + _("interface name is too short")); return FALSE; } - if (!strcmp (name, ".") || !strcmp (name, "..")) { + if ( name[0] == '.' + && ( name[1] == '\0' + || ( name[1] == '.' + && name[2] == '\0'))) { g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("interface name is reserved")); return FALSE; } - while (*name) { - if (*name == '/' || g_ascii_isspace (*name)) { + for (i = 0; i < IFNAMSIZ; i++) { + char ch = name[i]; + + if (ch == '\0') + return TRUE; + if ( NM_IN_SET (ch, '/', ':') + || g_ascii_isspace (ch)) { g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, _("interface name contains an invalid character")); return FALSE; } - name++; } - return TRUE; + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("interface name is longer than 15 characters")); + return FALSE; } /** @@ -3925,8 +3898,8 @@ _nm_utils_inet6_is_token (const struct in6_addr *in6addr) gboolean nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type) { - g_return_val_if_fail (_nm_setting_type_is_base_type (virtual_type), FALSE); - g_return_val_if_fail (_nm_setting_type_is_base_type (other_type), FALSE); + g_return_val_if_fail (_nm_setting_type_get_base_type_priority (virtual_type) != NM_SETTING_PRIORITY_INVALID, FALSE); + g_return_val_if_fail (_nm_setting_type_get_base_type_priority (other_type) != NM_SETTING_PRIORITY_INVALID, FALSE); if (virtual_type == NM_TYPE_SETTING_BOND) { return ( other_type == NM_TYPE_SETTING_INFINIBAND @@ -4038,28 +4011,29 @@ guint _nm_utils_strstrdictkey_hash (gconstpointer a) { const NMUtilsStrStrDictKey *k = a; - const signed char *p; - guint32 h = 5381; + const char *p; + NMHashState h; + nm_hash_init (&h, 76642997u); if (k) { if (((int) k->type) & ~STRSTRDICTKEY_ALL_SET) g_return_val_if_reached (0); - h = (h << 5) + h + k->type; + nm_hash_update_val (&h, k->type); if (k->type & STRSTRDICTKEY_ALL_SET) { - p = (void *) k->data; - for (; *p != '\0'; p++) - h = (h << 5) + h + *p; + gsize n; + + n = 0; + p = strchr (k->data, '\0'); if (k->type == STRSTRDICTKEY_ALL_SET) { /* the key contains two strings. Continue... */ - h = (h << 5) + h + '\0'; - for (p++; *p != '\0'; p++) - h = (h << 5) + h + *p; + p = strchr (p + 1, '\0'); } + if (p != k->data) + nm_hash_update (&h, k->data, p - k->data); } } - - return h; + return nm_hash_complete (&h); } gboolean @@ -4224,11 +4198,11 @@ out: * Returns: the index of the option in the array or -1 if was not * found. */ -int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option) +gssize _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option) { gboolean ret; char *option_name, *tmp_name; - int i; + guint i; if (!_nm_utils_dns_option_validate (option, &option_name, NULL, FALSE, NULL)) return -1; @@ -4249,82 +4223,7 @@ int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option) return -1; } -#define IS_FLAGS_SEPARATOR(ch) (NM_IN_SET ((ch), ' ', '\t', ',', '\n', '\r')) - -static gboolean -_is_hex_string (const char *str) -{ - return str[0] == '0' - && str[1] == 'x' - && str[2] - && NM_STRCHAR_ALL (&str[2], ch, g_ascii_isxdigit (ch)); -} - -static gboolean -_enum_is_valid_enum_nick (const char *str) -{ - return str[0] - && !NM_STRCHAR_ANY (str, ch, g_ascii_isspace (ch)) - && !NM_STRCHAR_ALL (str, ch, g_ascii_isdigit (ch)); -} - -static gboolean -_enum_is_valid_flags_nick (const char *str) -{ - return str[0] - && !NM_STRCHAR_ANY (str, ch, IS_FLAGS_SEPARATOR (ch)) - && !_is_hex_string (str); -} - -char * -_nm_utils_enum_to_str_full (GType type, - int value, - const char *flags_separator) -{ - GTypeClass *class; - char *ret; - - if ( flags_separator - && ( !flags_separator[0] - || NM_STRCHAR_ANY (flags_separator, ch, !IS_FLAGS_SEPARATOR (ch)))) - g_return_val_if_reached (NULL); - - class = g_type_class_ref (type); - - if (G_IS_ENUM_CLASS (class)) { - GEnumValue *enum_value; - - enum_value = g_enum_get_value (G_ENUM_CLASS (class), value); - if ( !enum_value - || !_enum_is_valid_enum_nick (enum_value->value_nick)) - ret = g_strdup_printf ("%d", value); - else - ret = strdup (enum_value->value_nick); - } else if (G_IS_FLAGS_CLASS (class)) { - GFlagsValue *flags_value; - GString *str = g_string_new (""); - - flags_separator = flags_separator ?: " "; - - while (value) { - flags_value = g_flags_get_first_value (G_FLAGS_CLASS (class), value); - if (str->len) - g_string_append (str, flags_separator); - if ( !flags_value - || !_enum_is_valid_flags_nick (flags_value->value_nick)) { - g_string_append_printf (str, "0x%x", (unsigned) value); - break; - } - g_string_append (str, flags_value->value_nick); - value &= ~flags_value->value; - } - ret = g_string_free (str, FALSE); - } else - g_return_val_if_reached (NULL); - - g_type_class_unref (class); - return ret; -} +/*****************************************************************************/ /** * nm_utils_enum_to_str: @@ -4333,8 +4232,9 @@ _nm_utils_enum_to_str_full (GType type, * * Converts an enum value to its string representation. If the enum is a * %G_TYPE_FLAGS the function returns a comma-separated list of matching values. - * If the enum is a %G_TYPE_ENUM and the given value is not valid the - * function returns %NULL. + * If the value has no corresponding string representation, it is converted + * to a number. For enums it is converted to a decimal number, for flags + * to an (unsigned) hex number. * * Returns: a newly allocated string or %NULL * @@ -4368,81 +4268,7 @@ gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token) { - GTypeClass *class; - gboolean ret = FALSE; - int value = 0; - gs_free char *str_clone = NULL; - char *s; - gint64 v64; - - g_return_val_if_fail (str, FALSE); - - str_clone = strdup (str); - s = nm_str_skip_leading_spaces (str_clone); - g_strchomp (s); - - class = g_type_class_ref (type); - - if (G_IS_ENUM_CLASS (class)) { - GEnumValue *enum_value; - - if (s[0]) { - if (NM_STRCHAR_ALL (s, ch, g_ascii_isdigit (ch))) { - v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXINT, -1); - if (v64 != -1) { - value = (int) v64; - ret = TRUE; - } - } else { - enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (class), s); - if (enum_value) { - value = enum_value->value; - ret = TRUE; - } - } - } - } else if (G_IS_FLAGS_CLASS (class)) { - GFlagsValue *flags_value; - - ret = TRUE; - while (s[0]) { - char *s_end; - - for (s_end = s; s_end[0]; s_end++) { - if (IS_FLAGS_SEPARATOR (s_end[0])) { - s_end[0] = '\0'; - s_end++; - break; - } - } - - if (s[0]) { - if (_is_hex_string (s)) { - v64 = _nm_utils_ascii_str_to_int64 (&s[2], 16, 0, G_MAXUINT, -1); - if (v64 == -1) { - ret = FALSE; - break; - } - value |= (int) v64; - } else { - flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (class), s); - if (!flags_value) { - ret = FALSE; - break; - } - value |= flags_value->value; - } - } - - s = s_end; - } - } else - g_return_val_if_reached (FALSE); - - NM_SET_OUT (err_token, !ret && s[0] ? g_strdup (s) : NULL); - NM_SET_OUT (out_value, ret ? value : 0); - g_type_class_unref (class); - return ret; + return _nm_utils_enum_from_str_full (type, str, out_value, err_token, NULL); } /** @@ -4460,52 +4286,11 @@ nm_utils_enum_from_str (GType type, const char *str, */ const char **nm_utils_enum_get_values (GType type, gint from, gint to) { - GTypeClass *class; - GPtrArray *array; - gint i; - char sbuf[64]; - - class = g_type_class_ref (type); - array = g_ptr_array_new (); - - if (G_IS_ENUM_CLASS (class)) { - GEnumClass *enum_class = G_ENUM_CLASS (class); - GEnumValue *enum_value; - - for (i = 0; i < enum_class->n_values; i++) { - enum_value = &enum_class->values[i]; - if (enum_value->value >= from && enum_value->value <= to) { - if (_enum_is_valid_enum_nick (enum_value->value_nick)) - g_ptr_array_add (array, (gpointer) enum_value->value_nick); - else - g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "%d", enum_value->value))); - } - } - } else if (G_IS_FLAGS_CLASS (class)) { - GFlagsClass *flags_class = G_FLAGS_CLASS (class); - GFlagsValue *flags_value; - - for (i = 0; i < flags_class->n_values; i++) { - flags_value = &flags_class->values[i]; - if (flags_value->value >= from && flags_value->value <= to) { - if (_enum_is_valid_flags_nick (flags_value->value_nick)) - g_ptr_array_add (array, (gpointer) flags_value->value_nick); - else - g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "0x%x", (unsigned) flags_value->value))); - } - } - } else { - g_type_class_unref (class); - g_ptr_array_free (array, TRUE); - g_return_val_if_reached (NULL); - } - - g_type_class_unref (class); - g_ptr_array_add (array, NULL); - - return (const char **) g_ptr_array_free (array, FALSE); + return _nm_utils_enum_get_values (type, from, to); } +/*****************************************************************************/ + #if WITH_JANSSON /** * nm_utils_is_json_object: @@ -4535,7 +4320,7 @@ nm_utils_is_json_object (const char *str, GError **error) return FALSE; } - json = json_loads (str, 0, &jerror); + json = json_loads (str, JSON_REJECT_DUPLICATES, &jerror); if (!json) { g_set_error (error, NM_CONNECTION_ERROR, @@ -4575,6 +4360,7 @@ _nm_utils_team_config_equal (const char *conf1, gboolean port_config) { json_t *json1 = NULL, *json2 = NULL, *json; + json_t *array, *name; gs_free char *dump1 = NULL, *dump2 = NULL; json_t *value, *property; json_error_t jerror; @@ -4587,9 +4373,9 @@ _nm_utils_team_config_equal (const char *conf1, return TRUE; /* A NULL configuration is equivalent to default value '{}' */ - json1 = json_loads (conf1 ?: "{}", 0, &jerror); + json1 = json_loads (conf1 ?: "{}", JSON_REJECT_DUPLICATES, &jerror); if (json1) - json2 = json_loads (conf2 ?: "{}", 0, &jerror); + json2 = json_loads (conf2 ?: "{}", JSON_REJECT_DUPLICATES, &jerror); if (!json1 || !json2) { ret = FALSE; @@ -4614,6 +4400,16 @@ _nm_utils_team_config_equal (const char *conf1, property = json_object (); json_object_set_new (property, "name", json_string ("roundrobin")); json_object_set_new (json, "runner", property); + } else if ( (name = json_object_get (property, "name")) + && NM_IN_STRSET (json_string_value (name), "lacp", "loadbalance")) { + /* Add default tx_hash when missing */ + if (!json_object_get (property, "tx_hash")) { + array = json_array (); + json_array_append_new (array, json_string ("eth")); + json_array_append_new (array, json_string ("ipv4")); + json_array_append_new (array, json_string ("ipv6")); + json_object_set_new (property, "tx_hash", array); + } } } } diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h index c6cd2892..f6bfaf72 100644 --- a/libnm-core/nm-version.h +++ b/libnm-core/nm-version.h @@ -132,4 +132,18 @@ # define NM_AVAILABLE_IN_1_8 #endif +#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_10 +# define NM_DEPRECATED_IN_1_10 G_DEPRECATED +# define NM_DEPRECATED_IN_1_10_FOR(f) G_DEPRECATED_FOR(f) +#else +# define NM_DEPRECATED_IN_1_10 +# define NM_DEPRECATED_IN_1_10_FOR(f) +#endif + +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_10 +# define NM_AVAILABLE_IN_1_10 G_UNAVAILABLE(1,10) +#else +# define NM_AVAILABLE_IN_1_10 +#endif + #endif /* NM_VERSION_H */ diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index ccde24f8..188cb28e 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -25,6 +25,9 @@ #include <string.h> +#include "nm-utils/c-list-util.h" +#include "nm-utils/nm-hash-utils.h" + #include "nm-utils.h" #include "nm-setting-private.h" #include "nm-utils.h" @@ -60,6 +63,7 @@ #include "nm-setting-wireless-security.h" #include "nm-simple-connection.h" #include "nm-keyfile-internal.h" +#include "nm-utils/nm-dedup-multi.h" #include "test-general-enums.h" @@ -75,6 +79,598 @@ G_STATIC_ASSERT (sizeof (bool) <= sizeof (int)); /*****************************************************************************/ +typedef struct _nm_packed { + int v0; + char v1; + double v2; + guint8 v3; +} TestHashStruct; + +static void +_test_hash_struct (int v0, char v1, double v2, guint8 v3) +{ + const TestHashStruct s = { + .v0 = v0, + .v1 = v1, + .v2 = v2, + .v3 = v3, + }; + NMHashState h; + guint hh; + + nm_hash_init (&h, 100); + nm_hash_update (&h, &s, sizeof (s)); + hh = nm_hash_complete (&h); + + nm_hash_init (&h, 100); + nm_hash_update_val (&h, v0); + nm_hash_update_val (&h, v1); + nm_hash_update_val (&h, v2); + nm_hash_update_val (&h, v3); + g_assert_cmpint (hh, ==, nm_hash_complete (&h)); + + nm_hash_init (&h, 100); + nm_hash_update_vals (&h, v0, v1, v2, v3); + g_assert_cmpint (hh, ==, nm_hash_complete (&h)); +} + +static guint +_test_hash_str (const char *str) +{ + NMHashState h; + guint v, v2; + const guint SEED = 10; + + nm_hash_init (&h, SEED); + nm_hash_update_str0 (&h, str); + v = nm_hash_complete (&h); + + /* assert that hashing a string and a buffer yields the + * same result. + * + * I think that is a desirable property. */ + nm_hash_init (&h, SEED); + nm_hash_update_mem (&h, str, strlen (str)); + v2 = nm_hash_complete (&h); + + g_assert (v == v2); + return v; +} + +#define _test_hash_vals(type, ...) \ + G_STMT_START { \ + NMHashState h0, h1, h2, h3; \ + const type v[] = { __VA_ARGS__ }; \ + guint h; \ + guint i; \ + \ + nm_hash_init (&h0, 10); \ + nm_hash_init (&h1, 10); \ + nm_hash_init (&h2, 10); \ + nm_hash_init (&h3, 10); \ + \ + /* assert that it doesn't matter, whether we hash the values individually, + * or all at once, or via the convenience macros nm_hash_update_val() + * and nm_hash_update_vals(). */ \ + for (i = 0; i < G_N_ELEMENTS (v); i++) { \ + nm_hash_update (&h0, &v[i], sizeof (type)); \ + nm_hash_update_val (&h1, v[i]); \ + } \ + nm_hash_update_vals (&h2, __VA_ARGS__); \ + nm_hash_update (&h3, v, sizeof (v)); \ + \ + h = nm_hash_complete (&h0); \ + g_assert_cmpint (h, ==, nm_hash_complete (&h1)); \ + g_assert_cmpint (h, ==, nm_hash_complete (&h2)); \ + g_assert_cmpint (h, ==, nm_hash_complete (&h3)); \ + } G_STMT_END + +static void +test_nm_hash (void) +{ + _test_hash_str (""); + _test_hash_str ("a"); + _test_hash_str ("aa"); + _test_hash_str ("diceros bicornis longipes"); + + /* assert that nm_hash_update_vals() is the same as calling nm_hash_update_val() multiple times. */ + _test_hash_vals (int, 1); + _test_hash_vals (int, 1, 2); + _test_hash_vals (int, 1, 2, 3); + _test_hash_vals (int, 1, 2, 3, 4); + _test_hash_vals (long, 1l); + _test_hash_vals (long, 1l, 2l, 3l, 4l, 5l); + + _test_hash_struct (10, 'a', 5.4, 7); + _test_hash_struct (-10, '\0', -5.4e49, 255); + + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 0), ==, 0x002); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1), ==, 0x003); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1, 0, 0, 0, 0), ==, 0x030); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 0, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031); + g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 1, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x131); +} + +/*****************************************************************************/ + +static void +test_nm_g_slice_free_fcn (void) +{ + gpointer p; + + p = g_slice_new (gint64); + (nm_g_slice_free_fcn (gint64)) (p); + + p = g_slice_new (gint32); + (nm_g_slice_free_fcn (gint32)) (p); + + p = g_slice_new (gint); + (nm_g_slice_free_fcn (gint)) (p); + + p = g_slice_new (gint64); + nm_g_slice_free_fcn_gint64 (p); +} + +/*****************************************************************************/ + +static void +_do_test_nm_utils_strsplit_set (const char *str, ...) +{ + gs_unref_ptrarray GPtrArray *args_array = g_ptr_array_new (); + const char *const*args; + gs_free const char **words = NULL; + const char *arg; + gsize i; + va_list ap; + + va_start (ap, str); + while ((arg = va_arg (ap, const char *))) + g_ptr_array_add (args_array, (gpointer) arg); + va_end (ap); + g_ptr_array_add (args_array, NULL); + + args = (const char *const*) args_array->pdata; + + words = nm_utils_strsplit_set (str, " \t\n"); + + if (!args[0]) { + g_assert (!words); + g_assert ( !str + || NM_STRCHAR_ALL (str, ch, NM_IN_SET (ch, ' ', '\t', '\n'))); + return; + } + g_assert (words); + for (i = 0; args[i] || words[i]; i++) { + g_assert (args[i]); + g_assert (words[i]); + g_assert (args[i][0]); + g_assert (NM_STRCHAR_ALL (args[i], ch, !NM_IN_SET (ch, ' ', '\t', '\n'))); + g_assert_cmpstr (args[i], ==, words[i]); + } +} + +#define do_test_nm_utils_strsplit_set(str, ...) \ + _do_test_nm_utils_strsplit_set (str, ##__VA_ARGS__, NULL) + +static void +test_nm_utils_strsplit_set (void) +{ + do_test_nm_utils_strsplit_set (NULL); + do_test_nm_utils_strsplit_set (""); + do_test_nm_utils_strsplit_set ("\t"); + do_test_nm_utils_strsplit_set (" \t\n"); + do_test_nm_utils_strsplit_set ("a", "a"); + do_test_nm_utils_strsplit_set ("a b", "a", "b"); + do_test_nm_utils_strsplit_set ("a\rb", "a\rb"); + do_test_nm_utils_strsplit_set (" a\rb ", "a\rb"); + do_test_nm_utils_strsplit_set (" a bbbd afds ere", "a", "bbbd", "afds", "ere"); + do_test_nm_utils_strsplit_set ("1 2 3 4 5 6 7 8 9 0 " + "1 2 3 4 5 6 7 8 9 0 " + "1 2 3 4 5 6 7 8 9 0", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); +} + +/*****************************************************************************/ + +typedef struct { + int val; + int idx; + CList lst; +} CListSort; + +static int +_c_list_sort_cmp (const CList *lst_a, const CList *lst_b, const void *user_data) +{ + const CListSort *a, *b; + + g_assert (lst_a); + g_assert (lst_b); + g_assert (lst_a != lst_b); + + a = c_list_entry (lst_a, CListSort, lst); + b = c_list_entry (lst_b, CListSort, lst); + + if (a->val < b->val) + return -1; + if (a->val > b->val) + return 1; + return 0; +} + +static void +test_c_list_sort (void) +{ + guint i, n_list, repeat, headless; + CList head, *iter, *iter_prev, *lst; + CListSort elements[30]; + const CListSort *el_prev; + + c_list_init (&head); + c_list_sort (&head, _c_list_sort_cmp, NULL); + g_assert (c_list_length (&head) == 0); + g_assert (c_list_is_empty (&head)); + + for (repeat = 0; repeat < 10; repeat++) { + for (n_list = 1; n_list < G_N_ELEMENTS (elements); n_list++) { + for (headless = 0; headless < 2; headless++) { + c_list_init (&head); + for (i = 0; i < n_list; i++) { + CListSort *el; + + el = &elements[i]; + el->val = nmtst_get_rand_int () % (2*n_list); + el->idx = i; + c_list_link_tail (&head, &el->lst); + } + + if (headless) { + lst = head.next; + c_list_unlink (&head); + lst = c_list_sort_headless (lst, _c_list_sort_cmp, NULL); + g_assert (lst); + g_assert (lst->next); + g_assert (lst->prev); + g_assert (c_list_length (lst) == n_list - 1); + iter_prev = lst->prev; + for (iter = lst; iter != lst; iter = iter->next) { + g_assert (iter); + g_assert (iter->next); + g_assert (iter->prev == iter_prev); + } + c_list_link_before (lst, &head); + } else { + c_list_sort (&head, _c_list_sort_cmp, NULL); + } + + g_assert (!c_list_is_empty (&head)); + g_assert (c_list_length (&head) == n_list); + + el_prev = NULL; + c_list_for_each (iter, &head) { + CListSort *el; + + el = c_list_entry (iter, CListSort, lst); + g_assert (el->idx >= 0 && el->idx < n_list); + g_assert (el == &elements[el->idx]); + if (el_prev) { + g_assert (el_prev->val <= el->val); + if (el_prev->val == el->val) + g_assert (el_prev->idx < el->idx); + g_assert (iter->prev == &el_prev->lst); + g_assert (el_prev->lst.next == iter); + } + el_prev = el; + } + g_assert (head.prev == &el_prev->lst); + } + } + } +} + +/*****************************************************************************/ + +typedef struct { + NMDedupMultiObj parent; + guint val; + guint other; +} DedupObj; + +static const NMDedupMultiObjClass dedup_obj_class; + +static DedupObj * +_dedup_obj_assert (const NMDedupMultiObj *obj) +{ + DedupObj *o; + + g_assert (obj); + o = (DedupObj *) obj; + g_assert (o->parent.klass == &dedup_obj_class); + g_assert (o->parent._ref_count > 0); + g_assert (o->val > 0); + return o; +} + +static const NMDedupMultiObj * +_dedup_obj_clone (const NMDedupMultiObj *obj) +{ + DedupObj *o, *o2; + + o = _dedup_obj_assert (obj); + o2 = g_slice_new0 (DedupObj); + o2->parent.klass = &dedup_obj_class; + o2->parent._ref_count = 1; + o2->val = o->val; + o2->other = o->other; + return (NMDedupMultiObj *) o2; +} + +static void +_dedup_obj_destroy (NMDedupMultiObj *obj) +{ + DedupObj *o = (DedupObj *) obj; + + nm_assert (o->parent._ref_count == 0); + o->parent._ref_count = 1; + o = _dedup_obj_assert (obj); + g_slice_free (DedupObj, o); +} + +static void +_dedup_obj_full_hash_update (const NMDedupMultiObj *obj, NMHashState *h) +{ + const DedupObj *o; + + o = _dedup_obj_assert (obj); + nm_hash_update_vals (h, + o->val, + o->other); +} + +static gboolean +_dedup_obj_full_equal (const NMDedupMultiObj *obj_a, + const NMDedupMultiObj *obj_b) +{ + const DedupObj *o_a = _dedup_obj_assert (obj_a); + const DedupObj *o_b = _dedup_obj_assert (obj_b); + + return o_a->val == o_b->val + && o_a->other == o_b->other; +} + +static const NMDedupMultiObjClass dedup_obj_class = { + .obj_clone = _dedup_obj_clone, + .obj_destroy = _dedup_obj_destroy, + .obj_full_hash_update = _dedup_obj_full_hash_update, + .obj_full_equal = _dedup_obj_full_equal, +}; + +#define DEDUP_OBJ_INIT(val_val, other_other) \ + (&((DedupObj) { \ + .parent = { \ + .klass = &dedup_obj_class, \ + ._ref_count = NM_OBJ_REF_COUNT_STACKINIT, \ + }, \ + .val = (val_val), \ + .other = (other_other), \ + })) + +typedef struct { + NMDedupMultiIdxType parent; + guint partition_size; + guint val_mod; +} DedupIdxType; + +static const NMDedupMultiIdxTypeClass dedup_idx_type_class; + +static const DedupIdxType * +_dedup_idx_assert (const NMDedupMultiIdxType *idx_type) +{ + DedupIdxType *t; + + g_assert (idx_type); + t = (DedupIdxType *) idx_type; + g_assert (t->parent.klass == &dedup_idx_type_class); + g_assert (t->partition_size > 0); + g_assert (t->val_mod > 0); + return t; +} + +static void +_dedup_idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj *obj, + NMHashState *h) +{ + const DedupIdxType *t; + const DedupObj *o; + + t = _dedup_idx_assert (idx_type); + o = _dedup_obj_assert (obj); + + nm_hash_update_val (h, o->val / t->partition_size); + nm_hash_update_val (h, o->val % t->val_mod); +} + +static gboolean +_dedup_idx_obj_id_equal (const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj *obj_a, + const NMDedupMultiObj *obj_b) +{ + const DedupIdxType *t; + const DedupObj *o_a; + const DedupObj *o_b; + + t = _dedup_idx_assert (idx_type); + o_a = _dedup_obj_assert (obj_a); + o_b = _dedup_obj_assert (obj_b); + + return (o_a->val / t->partition_size) == (o_b->val / t->partition_size) + && (o_a->val % t->val_mod) == (o_b->val % t->val_mod); +} + +static void +_dedup_idx_obj_partition_hash_update (const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj *obj, + NMHashState *h) +{ + const DedupIdxType *t; + const DedupObj *o; + + t = _dedup_idx_assert (idx_type); + o = _dedup_obj_assert (obj); + + nm_hash_update_val (h, o->val / t->partition_size); +} + +static gboolean +_dedup_idx_obj_partition_equal (const NMDedupMultiIdxType *idx_type, + const NMDedupMultiObj *obj_a, + const NMDedupMultiObj *obj_b) +{ + const DedupIdxType *t; + const DedupObj *o_a; + const DedupObj *o_b; + + t = _dedup_idx_assert (idx_type); + o_a = _dedup_obj_assert (obj_a); + o_b = _dedup_obj_assert (obj_b); + + return (o_a->val / t->partition_size) == (o_b->val / t->partition_size); +} + +static const NMDedupMultiIdxTypeClass dedup_idx_type_class = { + .idx_obj_id_hash_update = _dedup_idx_obj_id_hash_update, + .idx_obj_id_equal = _dedup_idx_obj_id_equal, + .idx_obj_partition_hash_update = _dedup_idx_obj_partition_hash_update, + .idx_obj_partition_equal = _dedup_idx_obj_partition_equal, +}; + +static const DedupIdxType * +DEDUP_IDX_TYPE_INIT (DedupIdxType *idx_type, guint partition_size, guint val_mod) +{ + nm_dedup_multi_idx_type_init ((NMDedupMultiIdxType *) idx_type, &dedup_idx_type_class); + idx_type->val_mod = val_mod; + idx_type->partition_size = partition_size; + return idx_type; +} + +static gboolean +_dedup_idx_add (NMDedupMultiIndex *idx, const DedupIdxType *idx_type, const DedupObj *obj, NMDedupMultiIdxMode mode, const NMDedupMultiEntry **out_entry) +{ + g_assert (idx); + _dedup_idx_assert ((NMDedupMultiIdxType *) idx_type); + if (obj) + _dedup_obj_assert ((NMDedupMultiObj *) obj); + return nm_dedup_multi_index_add (idx, (NMDedupMultiIdxType *) idx_type, + obj, mode, out_entry, NULL); +} + +static void +_dedup_head_entry_assert (const NMDedupMultiHeadEntry *entry) +{ + g_assert (entry); + g_assert (entry->len > 0); + g_assert (entry->len == c_list_length (&entry->lst_entries_head)); + g_assert (entry->idx_type); + g_assert (entry->is_head); +} + +static const DedupObj * +_dedup_entry_assert (const NMDedupMultiEntry *entry) +{ + g_assert (entry); + g_assert (!c_list_is_empty (&entry->lst_entries)); + g_assert (entry->head); + g_assert (!entry->is_head); + g_assert (entry->head != (gpointer) entry); + _dedup_head_entry_assert (entry->head); + return _dedup_obj_assert (entry->obj); +} + +static const DedupIdxType * +_dedup_entry_get_idx_type (const NMDedupMultiEntry *entry) +{ + _dedup_entry_assert (entry); + + g_assert (entry->head); + g_assert (entry->head->idx_type); + return _dedup_idx_assert (entry->head->idx_type); +} + +static void +_dedup_entry_assert_all (const NMDedupMultiEntry *entry, gssize expected_idx, const DedupObj *const*expected_obj) +{ + gsize n, i; + CList *iter; + + g_assert (entry); + _dedup_entry_assert (entry); + + g_assert (expected_obj); + n = NM_PTRARRAY_LEN (expected_obj); + + g_assert (n == c_list_length (&entry->lst_entries)); + + g_assert (expected_idx >= -1 && expected_idx < n); + g_assert (entry->head); + if (expected_idx == -1) + g_assert (entry->head == (gpointer) entry); + else + g_assert (entry->head != (gpointer) entry); + + i = 0; + c_list_for_each (iter, &entry->head->lst_entries_head) { + const NMDedupMultiEntry *entry_current = c_list_entry (iter, NMDedupMultiEntry, lst_entries); + const DedupObj *obj_current; + const DedupIdxType *idx_type = _dedup_entry_get_idx_type (entry_current); + + obj_current = _dedup_entry_assert (entry_current); + g_assert (obj_current); + g_assert (i < n); + if (expected_idx == i) + g_assert (entry_current == entry); + g_assert (idx_type->parent.klass->idx_obj_partition_equal (&idx_type->parent, + entry_current->obj, + c_list_entry (entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj)); + i++; + } +} +#define _dedup_entry_assert_all(entry, expected_idx, ...) _dedup_entry_assert_all (entry, expected_idx, (const DedupObj *const[]) { __VA_ARGS__, NULL }) + +static void +test_dedup_multi (void) +{ + NMDedupMultiIndex *idx; + DedupIdxType IDX_20_3_a_stack; + const DedupIdxType *const IDX_20_3_a = DEDUP_IDX_TYPE_INIT (&IDX_20_3_a_stack, 20, 3); + const NMDedupMultiEntry *entry1; + + idx = nm_dedup_multi_index_new (); + + g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 1), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1)); + _dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 1)); + + g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1))); + g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2))); + + g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1)); + _dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 2)); + + g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1))); + g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2))); + + g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (2, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1)); + _dedup_entry_assert_all (entry1, 1, DEDUP_OBJ_INIT (1, 2), DEDUP_OBJ_INIT (2, 2)); + + nm_dedup_multi_index_unref (idx); +} + +/*****************************************************************************/ + static NMConnection * _connection_new_from_dbus (GVariant *dict, GError **error) { @@ -1975,6 +2571,7 @@ test_connection_diff_a_only (void) { NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A }, { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN } } }, { NM_SETTING_WIRED_SETTING_NAME, { @@ -2003,6 +2600,7 @@ test_connection_diff_a_only (void) { NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_ROUTE_TABLE, 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 }, @@ -2834,7 +3432,7 @@ test_ip4_prefix_to_netmask (void) int i; for (i = 0; i<=32; i++) { - guint32 netmask = nm_utils_ip4_prefix_to_netmask (i); + guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i); int plen = nm_utils_ip4_netmask_to_prefix (netmask); g_assert_cmpint (i, ==, plen); @@ -2862,8 +3460,8 @@ test_ip4_netmask_to_prefix (void) g_rand_set_seed (rand, 1); for (i = 2; i<=32; i++) { - guint32 netmask = nm_utils_ip4_prefix_to_netmask (i); - guint32 netmask_lowest_bit = netmask & ~nm_utils_ip4_prefix_to_netmask (i-1); + guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i); + guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask (i-1); g_assert_cmpint (i, ==, nm_utils_ip4_netmask_to_prefix (netmask)); @@ -3008,7 +3606,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->dns->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3018,7 +3616,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->dns_search->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3030,7 +3628,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr)); ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->addresses->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3043,7 +3641,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route)); ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->routes->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3053,7 +3651,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_option (s_ip4, "debug")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->dns_options->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_options->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 1)); g_test_assert_expected_messages (); @@ -3084,7 +3682,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->dns->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3094,7 +3692,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com")); ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->dns_search->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3107,7 +3705,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr)); ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->addresses->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3120,7 +3718,7 @@ test_setting_ip6_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route)); ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0)); - g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx < priv->routes->len)); + g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len)); ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1)); g_test_assert_expected_messages (); @@ -3492,7 +4090,7 @@ _test_connection_normalize_type_normalizable_setting (const char *type, base_type = nm_setting_lookup_type (type); g_assert (base_type != G_TYPE_INVALID); - g_assert (_nm_setting_type_is_base_type (base_type)); + g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID); con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con); @@ -3522,7 +4120,7 @@ _test_connection_normalize_type_unnormalizable_setting (const char *type) base_type = nm_setting_lookup_type (type); g_assert (base_type != G_TYPE_INVALID); - g_assert (_nm_setting_type_is_base_type (base_type)); + g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID); con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con); @@ -3545,7 +4143,7 @@ _test_connection_normalize_type_normalizable_type (const char *type, base_type = nm_setting_lookup_type (type); g_assert (base_type != G_TYPE_INVALID); - g_assert (_nm_setting_type_is_base_type (base_type)); + g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID); con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con); @@ -3558,7 +4156,7 @@ _test_connection_normalize_type_normalizable_type (const char *type, nm_connection_add_setting (con, s_base); } - g_assert (!nm_connection_get_connection_type (con)); + g_assert (!nm_setting_connection_get_connection_type (s_con)); g_assert (nm_connection_get_setting_by_name (con, type) == s_base); nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); @@ -4058,6 +4656,344 @@ test_connection_normalize_shared_addresses (void) } static void +test_connection_normalize_ovs_interface_type_system (gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT (test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection *s_con; + NMSettingOvsInterface *s_ovs_if; + + con = nmtst_create_minimal_connection ("test_connection_normalize_ovs_interface_type_system", + NULL, + NM_SETTING_WIRED_SETTING_NAME, &s_con); + + switch (TEST_CASE) { + case 1: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING); + + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + s_ovs_if = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_if); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "system"); + break; + case 2: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "system"); + break; + case 3: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "system", + NULL); + nmtst_assert_connection_verifies_without_normalization (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + break; + case 4: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "internal", + NULL); + /* the setting doesn't verify, because the interface-type must be "system". */ + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 5: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "system", + NULL); + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + break; + case 6: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME, + NULL); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "system", + NULL); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 7: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME, + NULL); + + nm_connection_add_setting (con, nm_setting_bridge_port_new ()); + + s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_if)); + + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "system", + NULL); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + default: + g_assert_not_reached (); + break; + } +} + +static void +test_connection_normalize_ovs_interface_type_ovs_interface (gconstpointer test_data) +{ + const guint TEST_CASE = GPOINTER_TO_UINT (test_data); + gs_unref_object NMConnection *con = NULL; + NMSettingConnection *s_con; + NMSettingOvsInterface *s_ovs_if; + NMSettingOvsPatch *s_ovs_patch; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + + con = nmtst_create_minimal_connection ("test_connection_normalize_ovs_interface_type_ovs_interface", + NULL, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con); + s_ovs_if = nm_connection_get_setting_ovs_interface (con); + g_assert (s_ovs_if); + + switch (TEST_CASE) { + case 1: + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 2: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NULL); + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal"); + break; + case 3: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal"); + break; + case 4: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "internal", + NULL); + nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal"); + break; + case 5: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "internal", + NULL); + nm_connection_add_setting (con, nm_setting_ip4_config_new ()); + nm_connection_add_setting (con, nm_setting_ip6_config_new ()); + nm_connection_add_setting (con, nm_setting_proxy_new ()); + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting_ip4_config (con)); + s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (con)); + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, "auto", + NULL); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, "auto", + NULL); + nmtst_assert_connection_verifies_without_normalization (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + break; + case 6: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "internal", + NULL); + nmtst_assert_connection_verifies_and_normalizable (con); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal"); + break; + case 7: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "system", + NULL); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 8: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "bogus", + NULL); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + break; + case 9: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "patch", + NULL); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING); + break; + case 10: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "patch", + NULL); + nm_connection_add_setting (con, nm_setting_ovs_patch_new ()); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + break; + case 11: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME, "adsf", + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "patch", + NULL); + nm_connection_add_setting (con, nm_setting_ovs_patch_new ()); + nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY); + break; + case 12: + g_object_set (s_con, + NM_SETTING_CONNECTION_MASTER, "master0", + NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_CONNECTION_INTERFACE_NAME, "adsf", + NULL); + g_object_set (s_ovs_if, + NM_SETTING_OVS_INTERFACE_TYPE, "patch", + NULL); + s_ovs_patch = NM_SETTING_OVS_PATCH (nm_setting_ovs_patch_new ()); + nm_connection_add_setting (con, NM_SETTING (s_ovs_patch)); + g_object_set (s_ovs_patch, + NM_SETTING_OVS_PATCH_PEER, "1.2.3.4", + NULL); + nmtst_assert_connection_verifies_and_normalizable (con); + nmtst_connection_normalize (con); + nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_OVS_INTERFACE_SETTING_NAME, + NM_SETTING_OVS_PATCH_SETTING_NAME); + g_assert (s_con == nm_connection_get_setting_connection (con)); + g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con)); + g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME); + g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "patch"); + break; + default: + g_assert_not_reached (); + } +} + +static void test_setting_ip4_gateway (void) { NMConnection *conn; @@ -4375,6 +5311,88 @@ test_hexstr2bin (void) /*****************************************************************************/ +static void +_do_strquote (const char *str, gsize buf_len, const char *expected) +{ + char canary = (char) nmtst_get_rand_int (); + gs_free char *buf_full = g_malloc (buf_len + 2); + char *buf = &buf_full[1]; + const char *b; + + buf[-1] = canary; + buf[buf_len] = canary; + + if (buf_len == 0) { + b = nm_strquote (NULL, 0, str); + g_assert (b == NULL); + g_assert (expected == NULL); + b = nm_strquote (buf, 0, str); + g_assert (b == buf); + } else { + b = nm_strquote (buf, buf_len, str); + g_assert (b == buf); + g_assert (strlen (b) < buf_len); + g_assert_cmpstr (expected, ==, b); + } + + g_assert (buf[-1] == canary); + g_assert (buf[buf_len] == canary); +} + +static void +test_nm_strquote (void) +{ + _do_strquote (NULL, 0, NULL); + _do_strquote ("", 0, NULL); + _do_strquote ("a", 0, NULL); + _do_strquote ("ab", 0, NULL); + + _do_strquote (NULL, 1, ""); + _do_strquote (NULL, 2, "("); + _do_strquote (NULL, 3, "(n"); + _do_strquote (NULL, 4, "(nu"); + _do_strquote (NULL, 5, "(nul"); + _do_strquote (NULL, 6, "(null"); + _do_strquote (NULL, 7, "(null)"); + _do_strquote (NULL, 8, "(null)"); + _do_strquote (NULL, 100, "(null)"); + + _do_strquote ("", 1, ""); + _do_strquote ("", 2, "^"); + _do_strquote ("", 3, "\"\""); + _do_strquote ("", 4, "\"\""); + _do_strquote ("", 5, "\"\""); + _do_strquote ("", 100, "\"\""); + + _do_strquote ("a", 1, ""); + _do_strquote ("a", 2, "^"); + _do_strquote ("a", 3, "\"^"); + _do_strquote ("a", 4, "\"a\""); + _do_strquote ("a", 5, "\"a\""); + _do_strquote ("a", 6, "\"a\""); + _do_strquote ("a", 100, "\"a\""); + + _do_strquote ("ab", 1, ""); + _do_strquote ("ab", 2, "^"); + _do_strquote ("ab", 3, "\"^"); + _do_strquote ("ab", 4, "\"a^"); + _do_strquote ("ab", 5, "\"ab\""); + _do_strquote ("ab", 6, "\"ab\""); + _do_strquote ("ab", 7, "\"ab\""); + _do_strquote ("ab", 100, "\"ab\""); + + _do_strquote ("abc", 1, ""); + _do_strquote ("abc", 2, "^"); + _do_strquote ("abc", 3, "\"^"); + _do_strquote ("abc", 4, "\"a^"); + _do_strquote ("abc", 5, "\"ab^"); + _do_strquote ("abc", 6, "\"abc\""); + _do_strquote ("abc", 7, "\"abc\""); + _do_strquote ("abc", 100, "\"abc\""); +} + +/*****************************************************************************/ + #define UUID_NIL "00000000-0000-0000-0000-000000000000" #define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8" @@ -4655,6 +5673,81 @@ test_nm_utils_strstrdictkey (void) /*****************************************************************************/ +static guint +_g_strv_length (gconstpointer arr) +{ + return arr ? g_strv_length ((char **) arr) : 0; +} + +static void +test_nm_ptrarray_len (void) +{ +#define _PTRARRAY_cmp(len, arr) \ + G_STMT_START { \ + g_assert_cmpint (len, ==, NM_PTRARRAY_LEN (arr)); \ + g_assert_cmpint (len, ==, _g_strv_length (arr)); \ + } G_STMT_END +#define _PTRARRAY_LEN0(T) \ + G_STMT_START { \ + T **vnull = NULL; \ + T *const*vnull1 = NULL; \ + T *const*const vnull2 = NULL; \ + T *v0[] = { NULL }; \ + T *const*v01 = v0; \ + T *const*const v02 = v0; \ + T **const v03 = v0; \ + \ + _PTRARRAY_cmp (0, vnull); \ + _PTRARRAY_cmp (0, vnull1); \ + _PTRARRAY_cmp (0, vnull2); \ + _PTRARRAY_cmp (0, v0); \ + _PTRARRAY_cmp (0, v01); \ + _PTRARRAY_cmp (0, v02); \ + _PTRARRAY_cmp (0, v03); \ + } G_STMT_END + + _PTRARRAY_LEN0 (char); + _PTRARRAY_LEN0 (const char); + _PTRARRAY_LEN0 (int); + _PTRARRAY_LEN0 (const int); + _PTRARRAY_LEN0 (void *); + _PTRARRAY_LEN0 (void); + _PTRARRAY_LEN0 (const void); + +#define _PTRARRAY_LENn(T) \ + G_STMT_START { \ + T x[5] = { 0 }; \ + \ + T *v1[] = { &x[0], NULL }; \ + T *const*v11 = v1; \ + T *const*const v12 = v1; \ + T **const v13 = v1; \ + \ + T *v2[] = { &x[0], &x[1], NULL }; \ + T *const*v21 = v2; \ + T *const*const v22 = v2; \ + T **const v23 = v2; \ + \ + _PTRARRAY_cmp (1, v1); \ + _PTRARRAY_cmp (1, v11); \ + _PTRARRAY_cmp (1, v12); \ + _PTRARRAY_cmp (1, v13); \ + \ + _PTRARRAY_cmp (2, v2); \ + _PTRARRAY_cmp (2, v21); \ + _PTRARRAY_cmp (2, v22); \ + _PTRARRAY_cmp (2, v23); \ + } G_STMT_END + + _PTRARRAY_LENn (char); + _PTRARRAY_LENn (const char); + _PTRARRAY_LENn (int); + _PTRARRAY_LENn (const int); + _PTRARRAY_LENn (void *); +} + +/*****************************************************************************/ + static void test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs, gboolean exp_result, char *exp_name, gboolean exp_value) @@ -4808,10 +5901,26 @@ test_nm_utils_team_config_equal (void) "{ \"runner\" : { \"name\" : \"random\"} }", FALSE, TRUE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"loadbalance\"} }", + "{ \"runner\" : { \"name\" : \"loadbalance\"} }", + FALSE, + TRUE); _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }", "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }", FALSE, TRUE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }", + "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }", + FALSE, + TRUE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }", + "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }", + FALSE, + FALSE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }", + "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }", + FALSE, + FALSE); /* team port config */ _team_config_equal_check ("{ }", @@ -5209,7 +6318,7 @@ static void test_nm_utils_enum (void) test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67"); test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64"); - test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, ""); + test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none"); test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz"); test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO | NM_TEST_GENERAL_META_FLAGS_BAR | @@ -5707,8 +6816,12 @@ int main (int argc, char **argv) { nmtst_init (&argc, &argv, TRUE); - /* The tests */ + g_test_add_func ("/core/general/test_nm_hash", test_nm_hash); + g_test_add_func ("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn); + g_test_add_func ("/core/general/test_c_list_sort", test_c_list_sort); + g_test_add_func ("/core/general/test_dedup_multi", test_dedup_multi); g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe); + g_test_add_func ("/core/general/test_nm_utils_strsplit_set", test_nm_utils_strsplit_set); g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set); g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset); g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items); @@ -5766,6 +6879,25 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_connection_normalize_gateway_never_default", test_connection_normalize_gateway_never_default); g_test_add_func ("/core/general/test_connection_normalize_may_fail", test_connection_normalize_may_fail); g_test_add_func ("/core/general/test_connection_normalize_shared_addresses", test_connection_normalize_shared_addresses); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/1", GUINT_TO_POINTER (1), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/2", GUINT_TO_POINTER (2), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/3", GUINT_TO_POINTER (3), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/4", GUINT_TO_POINTER (4), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/5", GUINT_TO_POINTER (5), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/6", GUINT_TO_POINTER (6), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/7", GUINT_TO_POINTER (7), test_connection_normalize_ovs_interface_type_system); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/1", GUINT_TO_POINTER (1), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/2", GUINT_TO_POINTER (2), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/3", GUINT_TO_POINTER (3), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/4", GUINT_TO_POINTER (4), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/5", GUINT_TO_POINTER (5), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/6", GUINT_TO_POINTER (6), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/7", GUINT_TO_POINTER (7), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/8", GUINT_TO_POINTER (8), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/9", GUINT_TO_POINTER (9), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/10", GUINT_TO_POINTER (10), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/11", GUINT_TO_POINTER (11), test_connection_normalize_ovs_interface_type_ovs_interface); + g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/12", GUINT_TO_POINTER (12), test_connection_normalize_ovs_interface_type_ovs_interface); g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers); g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property); @@ -5811,6 +6943,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_setting_user_data", test_setting_user_data); g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin); + g_test_add_func ("/core/general/nm_strquote", test_nm_strquote); g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string); g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings); @@ -5820,6 +6953,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array); g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search); g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey); + g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len); g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate); g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx); diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c index 0149348d..3328e356 100644 --- a/libnm-core/tests/test-secrets.c +++ b/libnm-core/tests/test-secrets.c @@ -121,6 +121,12 @@ make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme) &error); nmtst_assert_success (success, error); + success = nm_setting_set_secret_flags (NM_SETTING (s_8021x), + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + &error); + nmtst_assert_success (success, error); + /* IP4 setting */ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); @@ -247,6 +253,13 @@ make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme) &error); nmtst_assert_success (success, error); + success = nm_setting_set_secret_flags (NM_SETTING (s_8021x), + NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, + NM_SETTING_SECRET_FLAG_AGENT_OWNED, + &error); + nmtst_assert_success (success, error); + + /* IP4 setting */ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); |