diff options
Diffstat (limited to 'libnm-util/nm-setting-wired.c')
| -rw-r--r-- | libnm-util/nm-setting-wired.c | 414 |
1 files changed, 398 insertions, 16 deletions
diff --git a/libnm-util/nm-setting-wired.c b/libnm-util/nm-setting-wired.c index 2f252433..ad47ac94 100644 --- a/libnm-util/nm-setting-wired.c +++ b/libnm-util/nm-setting-wired.c @@ -19,16 +19,20 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2010 Red Hat, Inc. * (C) Copyright 2007 - 2008 Novell, Inc. */ +#include <string.h> +#include <ctype.h> #include <net/ethernet.h> #include <dbus/dbus-glib.h> + #include "nm-setting-wired.h" #include "nm-param-spec-specialized.h" #include "nm-utils.h" #include "nm-utils-private.h" +#include "nm-dbus-glib-types.h" GQuark nm_setting_wired_error_quark (void) @@ -73,8 +77,12 @@ typedef struct { guint32 speed; char *duplex; gboolean auto_negotiate; - GByteArray *mac_address; + GByteArray *device_mac_address; + GByteArray *cloned_mac_address; guint32 mtu; + GPtrArray *s390_subchannels; + char *s390_nettype; + GHashTable *s390_options; } NMSettingWiredPrivate; enum { @@ -84,11 +92,25 @@ enum { PROP_DUPLEX, PROP_AUTO_NEGOTIATE, PROP_MAC_ADDRESS, + PROP_CLONED_MAC_ADDRESS, PROP_MTU, + PROP_S390_SUBCHANNELS, + PROP_S390_NETTYPE, + PROP_S390_OPTIONS, LAST_PROP }; +static const char *valid_s390_opts[] = { + "portno", "layer2", "portname", "protocol", "priority_queueing", + "buffer_count", "isolation", "total", "inter", "inter_jumbo", "route4", + "route6", "fake_broadcast", "broadcast_mode", "canonical_macaddr", + "checksumming", "sniffer", "large_send", "ipato_enable", "ipato_invert4", + "ipato_add4", "ipato_invert6", "ipato_add6", "vipa_add4", "vipa_add6", + "rxip_add4", "rxip_add6", "lancmd_timeout", + NULL +}; + NMSetting * nm_setting_wired_new (void) { @@ -132,7 +154,15 @@ nm_setting_wired_get_mac_address (NMSettingWired *setting) { g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); - return NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address; + return NM_SETTING_WIRED_GET_PRIVATE (setting)->device_mac_address; +} + +const GByteArray * +nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address; } guint32 @@ -143,12 +173,197 @@ nm_setting_wired_get_mtu (NMSettingWired *setting) return NM_SETTING_WIRED_GET_PRIVATE (setting)->mtu; } +/** + * nm_setting_wired_get_s390_subchannels: + * @setting: the #NMSettingWired + * + * Return the list of s390 subchannels that identify the device that this + * connection is applicable to. The connection should only be used in + * conjunction with that device. + * + * Returns: a #GPtrArray of strings, each specifying one subchannel the + * s390 device uses to communicate to the host. + **/ +const GPtrArray * +nm_setting_wired_get_s390_subchannels (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_subchannels; +} + +/** + * nm_setting_wired_get_s390_nettype: + * @setting: the #NMSettingWired + * + * Returns the s390 device type this connection should apply to. Will be one + * of 'qeth', 'lcs', or 'ctcm'. + * + * Returns: the s390 device type + **/ +const char * +nm_setting_wired_get_s390_nettype (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + + return NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_nettype; +} + +/** + * nm_setting_wired_get_num_s390_options: + * @setting: the #NMSettingWired + * + * Returns the number of s390-specific options that should be set for this + * device when it is activated. This can be used to retrieve each s390 + * option individually using nm_setting_wired_get_s390_option(). + * + * Returns: the number of s390-specific device options + **/ +guint32 +nm_setting_wired_get_num_s390_options (NMSettingWired *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0); + + return g_hash_table_size (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options); +} + +/** + * nm_setting_wired_get_s390_option: + * @setting: the #NMSettingWired + * @idx: index of the desired option, from 0 to + * nm_setting_wired_get_num_s390_options() - 1 + * @out_key: on return, the key name of the s390 specific option; this value is + * owned by the setting and should not be modified + * @out_value: on return, the value of the key of the s390 specific option; this + * value is owned by the setting and should not be modified + * + * Given an index, return the value of the s390 option at that index. indexes + * are *not* guaranteed to be static across modifications to options done by + * nm_setting_wired_add_s390_option() and nm_setting_wired_remove_s390_option(), + * and should not be used to refer to options except for short periods of time + * such as during option iteration. + * + * Returns: %TRUE on success if the index was valid and an option was found, + * %FALSE if the index was invalid (ie, greater than the number of options + * currently held by the setting) + **/ +gboolean +nm_setting_wired_get_s390_option (NMSettingWired *setting, + guint32 idx, + const char **out_key, + const char **out_value) +{ + NMSettingWiredPrivate *priv; + guint32 num_keys; + GList *keys; + const char *_key = NULL, *_value = NULL; + + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE); + + priv = NM_SETTING_WIRED_GET_PRIVATE (setting); + + num_keys = nm_setting_wired_get_num_s390_options (setting); + g_return_val_if_fail (idx < num_keys, FALSE); + + keys = g_hash_table_get_keys (priv->s390_options); + _key = g_list_nth_data (keys, idx); + _value = g_hash_table_lookup (priv->s390_options, _key); + + if (out_key) + *out_key = _key; + if (out_value) + *out_value = _value; + return TRUE; +} + +/** + * nm_setting_wired_get_s390_option_by_key: + * @setting: the #NMSettingWired + * @key: the key for which to retrieve the value + * + * Returns the value associated with the s390-specific option specified by + * @key, if it exists. + * + * Returns: the value, or NULL if the key/value pair was never added to the + * setting; the value is owned by the setting and must not be modified + **/ +const char * +nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting, + const char *key) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL); + g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (strlen (key), NULL); + + return g_hash_table_lookup (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key); +} + +/** + * nm_setting_wired_add_s390_options: + * @setting: the #NMSettingWired + * @key: key name for the option + * @value: value for the option + * + * Add an option to the table. The option is compared to an internal list + * of allowed options. Key names may contain only alphanumeric characters + * (ie [a-zA-Z0-9]). Adding a new key replaces any existing key/value pair that + * may already exist. + * + * Returns: %TRUE if the option was valid and was added to the internal option + * list, %FALSE if it was not. + **/ +gboolean nm_setting_wired_add_s390_option (NMSettingWired *setting, + const char *key, + const char *value) +{ + size_t value_len; + + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (strlen (key), FALSE); + g_return_val_if_fail (_nm_utils_string_in_list (key, valid_s390_opts), FALSE); + g_return_val_if_fail (value != NULL, FALSE); + + value_len = strlen (value); + g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE); + + g_hash_table_insert (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, + g_strdup (key), + g_strdup (value)); + return TRUE; +} + +/** + * nm_setting_wired_remove_s390_options: + * @setting: the #NMSettingWired + * @key: key name for the option to remove + * + * Remove the s390-specific option referenced by @key from the internal option + * list. + * + * Returns: %TRUE if the option was found and removed from the internal option + * list, %FALSE if it was not. + **/ +gboolean +nm_setting_wired_remove_s390_option (NMSettingWired *setting, + const char *key) +{ + g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (strlen (key), FALSE); + + return g_hash_table_remove (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key); +} + static gboolean verify (NMSetting *setting, GSList *all_settings, GError **error) { NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting); const char *valid_ports[] = { "tp", "aui", "bnc", "mii", NULL }; const char *valid_duplex[] = { "half", "full", NULL }; + const char *valid_nettype[] = { "qeth", "lcs", "ctcm", NULL }; + GHashTableIter iter; + const char *key, *value; if (priv->port && !_nm_utils_string_in_list (priv->port, valid_ports)) { g_set_error (error, @@ -166,7 +381,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error) return FALSE; } - if (priv->mac_address && priv->mac_address->len != ETH_ALEN) { + if (priv->device_mac_address && priv->device_mac_address->len != ETH_ALEN) { g_set_error (error, NM_SETTING_WIRED_ERROR, NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, @@ -174,13 +389,54 @@ verify (NMSetting *setting, GSList *all_settings, GError **error) return FALSE; } + if ( priv->s390_subchannels + && !(priv->s390_subchannels->len == 3 || priv->s390_subchannels->len == 2)) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_S390_SUBCHANNELS); + return FALSE; + } + + if (priv->s390_nettype && !_nm_utils_string_in_list (priv->s390_nettype, valid_nettype)) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_S390_NETTYPE); + return FALSE; + } + + g_hash_table_iter_init (&iter, priv->s390_options); + while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) { + if ( !_nm_utils_string_in_list (key, valid_s390_opts) + || !strlen (value) + || (strlen (value) > 200)) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_S390_OPTIONS); + return FALSE; + } + } + + if (priv->cloned_mac_address && priv->cloned_mac_address->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIRED_ERROR, + NM_SETTING_WIRED_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRED_CLONED_MAC_ADDRESS); + return FALSE; + } + return TRUE; } static void nm_setting_wired_init (NMSettingWired *setting) { + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting); + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRED_SETTING_NAME, NULL); + priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } static void @@ -190,18 +446,31 @@ finalize (GObject *object) g_free (priv->port); g_free (priv->duplex); + g_free (priv->s390_nettype); + + g_hash_table_destroy (priv->s390_options); + + if (priv->device_mac_address) + g_byte_array_free (priv->device_mac_address, TRUE); - if (priv->mac_address) - g_byte_array_free (priv->mac_address, TRUE); + if (priv->cloned_mac_address) + g_byte_array_free (priv->cloned_mac_address, TRUE); G_OBJECT_CLASS (nm_setting_wired_parent_class)->finalize (object); } static void +copy_hash (gpointer key, gpointer value, gpointer user_data) +{ + g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), g_strdup (value)); +} + +static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object); + GHashTable *new_hash; switch (prop_id) { case PROP_PORT: @@ -219,13 +488,36 @@ set_property (GObject *object, guint prop_id, priv->auto_negotiate = g_value_get_boolean (value); break; case PROP_MAC_ADDRESS: - if (priv->mac_address) - g_byte_array_free (priv->mac_address, TRUE); - priv->mac_address = g_value_dup_boxed (value); + if (priv->device_mac_address) + g_byte_array_free (priv->device_mac_address, TRUE); + priv->device_mac_address = g_value_dup_boxed (value); + break; + case PROP_CLONED_MAC_ADDRESS: + if (priv->cloned_mac_address) + g_byte_array_free (priv->cloned_mac_address, TRUE); + priv->cloned_mac_address = g_value_dup_boxed (value); break; case PROP_MTU: priv->mtu = g_value_get_uint (value); break; + case PROP_S390_SUBCHANNELS: + if (priv->s390_subchannels) { + g_ptr_array_foreach (priv->s390_subchannels, (GFunc) g_free, NULL); + g_ptr_array_free (priv->s390_subchannels, TRUE); + } + priv->s390_subchannels = g_value_dup_boxed (value); + break; + case PROP_S390_NETTYPE: + g_free (priv->s390_nettype); + priv->s390_nettype = g_value_dup_string (value); + break; + case PROP_S390_OPTIONS: + /* Must make a deep copy of the hash table here... */ + g_hash_table_remove_all (priv->s390_options); + new_hash = g_value_get_boxed (value); + if (new_hash) + g_hash_table_foreach (new_hash, copy_hash, priv->s390_options); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -234,9 +526,10 @@ set_property (GObject *object, guint prop_id, static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { NMSettingWired *setting = NM_SETTING_WIRED (object); + NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting); switch (prop_id) { case PROP_PORT: @@ -254,9 +547,21 @@ get_property (GObject *object, guint prop_id, case PROP_MAC_ADDRESS: g_value_set_boxed (value, nm_setting_wired_get_mac_address (setting)); break; + case PROP_CLONED_MAC_ADDRESS: + g_value_set_boxed (value, nm_setting_wired_get_cloned_mac_address (setting)); + break; case PROP_MTU: g_value_set_uint (value, nm_setting_wired_get_mtu (setting)); break; + case PROP_S390_SUBCHANNELS: + g_value_set_boxed (value, nm_setting_wired_get_s390_subchannels (setting)); + break; + case PROP_S390_NETTYPE: + g_value_set_string (value, nm_setting_wired_get_s390_nettype (setting)); + break; + case PROP_S390_OPTIONS: + g_value_set_boxed (value, priv->s390_options); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -351,21 +656,37 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class) * NMSettingWired:mac-address: * * If specified, this connection will only apply to the ethernet device - * whose MAC address matches. This property does not change the MAC address - * of the device (known as MAC spoofing). + * whose permanent MAC address matches. This property does not change the MAC address + * of the device (i.e. MAC spoofing). **/ g_object_class_install_property (object_class, PROP_MAC_ADDRESS, _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS, - "MAC Address", + "Device MAC Address", "If specified, this connection will only apply to " - "the ethernet device whose MAC address matches. " + "the ethernet device whose permanent MAC address matches. " "This property does not change the MAC address " - "of the device (known as MAC spoofing).", + "of the device (i.e. MAC spoofing).", DBUS_TYPE_G_UCHAR_ARRAY, G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); /** + * NMSettingWired:cloned-mac-address: + * + * If specified, request that the device use this MAC address instead of its + * permanent MAC address. This is known as MAC cloning or spoofing. + **/ + g_object_class_install_property + (object_class, PROP_CLONED_MAC_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + "Cloned MAC Address", + "If specified, request that the device use " + "this MAC address instead of its permanent MAC address. " + "This is known as MAC cloning or spoofing.", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** * NMSettingWired:mtu: * * If non-zero, only transmit packets of the specified size or smaller, @@ -380,5 +701,66 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class) "multiple Ethernet frames.", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE)); + + /** + * NMSettingWired:s390-subchannels: + * + * Identifies specific subchannels that this network device uses for + * communcation with z/VM or s390 host. Like #NMSettingWired:mac-address + * for non-z/VM devices, this property can be used to ensure this connection + * only applies to the network device that uses these subchannels. The + * list should contain exactly 3 strings, and each string may only be + * composed of hexadecimal characters and the period (.) character. + **/ + g_object_class_install_property + (object_class, PROP_S390_SUBCHANNELS, + _nm_param_spec_specialized (NM_SETTING_WIRED_S390_SUBCHANNELS, + "z/VM Subchannels", + "Identifies specific subchannels that this " + "network device uses for communcation with z/VM " + "or s390 host. Like the 'mac-address' property " + "for non-z/VM devices, this property can be used " + "to ensure this connection only applies to the " + "network device that uses these subchannels. The " + "list should contain exactly 3 strings, and each " + "string may only be composed of hexadecimal " + "characters and the period (.) character.", + DBUS_TYPE_G_ARRAY_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:s390-nettype: + * + * s390 network device type; one of 'qeth', 'lcs', or 'ctc', representing + * the different types of virtual network devices available on s390 systems. + **/ + g_object_class_install_property + (object_class, PROP_S390_NETTYPE, + g_param_spec_string (NM_SETTING_WIRED_S390_NETTYPE, + "s390 Net Type", + "s390 network device type; one of 'qeth', 'lcs', or " + "'ctc', representing the different types of virtual " + "network devices available on s390 systems.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWired:s390-options: + * + * Dictionary of key/value pairs of s390-specific device options. Both keys + * and values must be strings. Allowed keys include 'portno', 'layer2', + * 'portname', 'protocol', among others. Key names must contain only + * alphanumeric characters (ie, [a-zA-Z0-9]). + **/ + g_object_class_install_property + (object_class, PROP_S390_OPTIONS, + _nm_param_spec_specialized (NM_SETTING_WIRED_S390_OPTIONS, + "s390 Options", + "Dictionary of key/value pairs of s390-specific " + "device options. Both keys and values must be " + "strings. Allowed keys include 'portno', " + "'layer2', 'portname', 'protocol', among others.", + DBUS_TYPE_G_MAP_OF_STRING, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); } |