Merge remote branch 'origin/zvm'

This commit is contained in:
Dan Williams 2010-08-03 15:49:31 -07:00
commit 4898f8cd3d
13 changed files with 1164 additions and 22 deletions

View file

@ -290,6 +290,13 @@ global:
nm_setting_wired_get_mac_address;
nm_setting_wired_get_cloned_mac_address;
nm_setting_wired_get_mtu;
nm_setting_wired_get_num_s390_options;
nm_setting_wired_get_s390_nettype;
nm_setting_wired_get_s390_option;
nm_setting_wired_get_s390_option_by_key;
nm_setting_wired_add_s390_option;
nm_setting_wired_get_s390_subchannels;
nm_setting_wired_remove_s390_option;
nm_setting_wireless_ap_security_compatible;
nm_setting_wireless_error_get_type;
nm_setting_wireless_error_quark;

View file

@ -23,12 +23,16 @@
* (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)
@ -76,6 +80,9 @@ typedef struct {
GByteArray *device_mac_address;
GByteArray *cloned_mac_address;
guint32 mtu;
GPtrArray *s390_subchannels;
char *s390_nettype;
GHashTable *s390_options;
} NMSettingWiredPrivate;
enum {
@ -87,10 +94,23 @@ enum {
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)
{
@ -153,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,
@ -184,6 +389,36 @@ 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,
@ -198,7 +433,10 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
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
@ -208,6 +446,9 @@ 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);
@ -218,11 +459,18 @@ finalize (GObject *object)
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:
@ -252,6 +500,24 @@ set_property (GObject *object, guint prop_id,
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;
@ -260,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:
@ -286,6 +553,15 @@ get_property (GObject *object, guint prop_id,
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;
@ -425,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 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 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));
}

View file

@ -59,6 +59,9 @@ GQuark nm_setting_wired_error_quark (void);
#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address"
#define NM_SETTING_WIRED_CLONED_MAC_ADDRESS "cloned-mac-address"
#define NM_SETTING_WIRED_MTU "mtu"
#define NM_SETTING_WIRED_S390_SUBCHANNELS "s390-subchannels"
#define NM_SETTING_WIRED_S390_NETTYPE "s390-nettype"
#define NM_SETTING_WIRED_S390_OPTIONS "s390-options"
typedef struct {
NMSetting parent;
@ -76,14 +79,30 @@ typedef struct {
GType nm_setting_wired_get_type (void);
NMSetting *nm_setting_wired_new (void);
const char *nm_setting_wired_get_port (NMSettingWired *setting);
guint32 nm_setting_wired_get_speed (NMSettingWired *setting);
const char *nm_setting_wired_get_duplex (NMSettingWired *setting);
gboolean nm_setting_wired_get_auto_negotiate (NMSettingWired *setting);
const GByteArray *nm_setting_wired_get_mac_address (NMSettingWired *setting);
NMSetting * nm_setting_wired_new (void);
const char * nm_setting_wired_get_port (NMSettingWired *setting);
guint32 nm_setting_wired_get_speed (NMSettingWired *setting);
const char * nm_setting_wired_get_duplex (NMSettingWired *setting);
gboolean nm_setting_wired_get_auto_negotiate (NMSettingWired *setting);
const GByteArray *nm_setting_wired_get_mac_address (NMSettingWired *setting);
const GByteArray *nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting);
guint32 nm_setting_wired_get_mtu (NMSettingWired *setting);
guint32 nm_setting_wired_get_mtu (NMSettingWired *setting);
const GPtrArray * nm_setting_wired_get_s390_subchannels (NMSettingWired *setting);
const char * nm_setting_wired_get_s390_nettype (NMSettingWired *setting);
guint32 nm_setting_wired_get_num_s390_options (NMSettingWired *setting);
gboolean nm_setting_wired_get_s390_option (NMSettingWired *setting,
guint32 idx,
const char **out_key,
const char **out_value);
const char * nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
const char *key);
gboolean nm_setting_wired_add_s390_option (NMSettingWired *setting,
const char *key,
const char *item);
gboolean nm_setting_wired_remove_s390_option (NMSettingWired *setting,
const char *key);
G_END_DECLS

View file

@ -567,6 +567,24 @@ nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
g_value_take_boxed (dest_value, g_slist_reverse (list));
}
static void
nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
{
char **str;
GPtrArray *array = NULL;
guint i = 0;
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
str = (char **) g_value_get_boxed (src_value);
array = g_ptr_array_sized_new (3);
while (str && str[i])
g_ptr_array_add (array, g_strdup (str[i++]));
g_value_take_boxed (dest_value, array);
}
static void
nm_utils_convert_strv_to_string (const GValue *src_value, GValue *dest_value)
{
@ -593,6 +611,32 @@ nm_utils_convert_strv_to_string (const GValue *src_value, GValue *dest_value)
g_string_free (printable, FALSE);
}
static void
nm_utils_convert_string_array_to_string (const GValue *src_value, GValue *dest_value)
{
GPtrArray *strings;
GString *printable;
int i;
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_STRING));
strings = (GPtrArray *) g_value_get_boxed (src_value);
printable = g_string_new ("[");
for (i = 0; strings && i < strings->len; i++) {
if (i > 0)
g_string_append (printable, ", '");
else
g_string_append_c (printable, '\'');
g_string_append (printable, g_ptr_array_index (strings, i));
g_string_append_c (printable, '\'');
}
g_string_append_c (printable, ']');
g_value_take_string (dest_value, printable->str);
g_string_free (printable, FALSE);
}
static void
nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value)
{
@ -1055,9 +1099,15 @@ _nm_utils_register_value_transformations (void)
g_value_register_transform_func (G_TYPE_STRV,
DBUS_TYPE_G_LIST_OF_STRING,
nm_utils_convert_strv_to_slist);
g_value_register_transform_func (G_TYPE_STRV,
DBUS_TYPE_G_ARRAY_OF_STRING,
nm_utils_convert_strv_to_ptrarray);
g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
G_TYPE_STRING,
nm_utils_convert_strv_to_string);
g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_STRING,
G_TYPE_STRING,
nm_utils_convert_string_array_to_string);
g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY,
G_TYPE_STRING,
nm_utils_convert_uint_array_to_string);

View file

@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
@ -487,6 +488,101 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
return FALSE;
}
#define BUFSIZE 10
static gboolean
parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
{
long unsigned int tmp;
char buf[BUFSIZE + 1];
const char *p = subchannels;
int i = 0;
char *pa = NULL, *pb = NULL, *pc = NULL;
g_return_val_if_fail (subchannels != NULL, FALSE);
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (*a == 0, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
g_return_val_if_fail (*b == 0, FALSE);
g_return_val_if_fail (c != NULL, FALSE);
g_return_val_if_fail (*c == 0, FALSE);
/* sanity check */
if (!isxdigit (subchannels[0]))
return FALSE;
/* Get the first channel */
while (*p && (*p != ',')) {
if (!isxdigit (*p) && (*p != '.'))
return FALSE; /* Invalid chars */
if (i >= BUFSIZE)
return FALSE; /* Too long to be a subchannel */
buf[i++] = *p++;
}
buf[i] = '\0';
/* and grab each of its elements, there should be 3 */
pa = &buf[0];
pb = strchr (buf, '.');
if (pb)
pc = strchr (pb + 1, '.');
if (!pa || !pb || !pc)
return FALSE;
/* Split the string */
*pb++ = '\0';
*pc++ = '\0';
errno = 0;
tmp = strtoul (pa, NULL, 16);
if (errno)
return FALSE;
*a = (guint32) tmp;
errno = 0;
tmp = strtoul (pb, NULL, 16);
if (errno)
return FALSE;
*b = (guint32) tmp;
errno = 0;
tmp = strtoul (pc, NULL, 16);
if (errno)
return FALSE;
*c = (guint32) tmp;
return TRUE;
}
#define SUBCHAN_TAG "s390-subchannels:"
gboolean
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
{
const GSList *iter;
guint32 a = 0, b = 0, c = 0;
guint32 spec_a = 0, spec_b = 0, spec_c = 0;
g_return_val_if_fail (subchannels != NULL, FALSE);
if (!parse_subchannels (subchannels, &a, &b, &c))
return FALSE;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec = iter->data;
if (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) {
spec += strlen (SUBCHAN_TAG);
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
if (a == spec_a && b == spec_b && c == spec_c)
return TRUE;
}
}
}
return FALSE;
}
/*********************************/
static void

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2004 - 2008 Red Hat, Inc.
* Copyright (C) 2004 - 2010 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
*/
@ -48,6 +48,7 @@ void nm_utils_call_dispatcher (const char *action,
const char *vpn_iface);
gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
GHashTable *value_hash_create (void);

View file

@ -34,6 +34,9 @@
#include <linux/if.h>
#include <errno.h>
#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
#include <gudev/gudev.h>
#include <netlink/route/addr.h>
#include "nm-glib-compat.h"
@ -116,6 +119,12 @@ typedef struct {
Supplicant supplicant;
guint supplicant_timeout_id;
/* s390 */
char * subchan1;
char * subchan2;
char * subchan3;
char * subchannels; /* Composite used for checking unmanaged specs */
/* PPPoE */
NMPPPManager *ppp_manager;
NMIP4Config *pending_ip4_config;
@ -291,6 +300,109 @@ carrier_off (NMNetlinkMonitor *monitor,
}
}
static void
_update_s390_subchannels (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
const char *iface;
GUdevClient *client;
GUdevDevice *dev;
GUdevDevice *parent;
const char *parent_path, *item, *driver;
const char *subsystems[] = { "net", NULL };
GDir *dir;
GError *error = NULL;
iface = nm_device_get_iface (NM_DEVICE (self));
client = g_udev_client_new (subsystems);
if (!client) {
nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to initialize GUdev client", iface);
return;
}
dev = g_udev_client_query_by_subsystem_and_name (client, "net", iface);
if (!dev) {
nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to find device with udev", iface);
goto out;
}
/* Try for the "ccwgroup" parent */
parent = g_udev_device_get_parent_with_subsystem (dev, "ccwgroup", NULL);
if (!parent) {
/* FIXME: whatever 'lcs' devices' subsystem is here... */
if (!parent) {
/* Not an s390 device */
goto out;
}
}
parent_path = g_udev_device_get_sysfs_path (parent);
dir = g_dir_open (parent_path, 0, &error);
if (!dir) {
nm_log_warn (LOGD_DEVICE | LOGD_HW, "(%s): failed to open directory '%s': %s",
iface, parent_path,
error && error->message ? error->message : "(unknown)");
g_clear_error (&error);
goto out;
}
/* FIXME: we probably care about ordering here to ensure that we map
* cdev0 -> subchan1, cdev1 -> subchan2, etc.
*/
while ((item = g_dir_read_name (dir))) {
char buf[50];
char *cdev_path;
if (strncmp (item, "cdev", 4))
continue; /* Not a subchannel link */
cdev_path = g_strdup_printf ("%s/%s", parent_path, item);
memset (buf, 0, sizeof (buf));
errno = 0;
if (readlink (cdev_path, &buf[0], sizeof (buf) - 1) >= 0) {
if (!priv->subchan1)
priv->subchan1 = g_path_get_basename (buf);
else if (!priv->subchan2)
priv->subchan2 = g_path_get_basename (buf);
else if (!priv->subchan3)
priv->subchan3 = g_path_get_basename (buf);
} else {
nm_log_warn (LOGD_DEVICE | LOGD_HW,
"(%s): failed to read cdev link '%s': %s",
iface, cdev_path, errno);
}
g_free (cdev_path);
};
g_dir_close (dir);
if (priv->subchan3) {
priv->subchannels = g_strdup_printf ("%s,%s,%s",
priv->subchan1,
priv->subchan2,
priv->subchan3);
} else if (priv->subchan2) {
priv->subchannels = g_strdup_printf ("%s,%s",
priv->subchan1,
priv->subchan2);
} else
priv->subchannels = g_strdup (priv->subchan1);
driver = nm_device_get_driver (NM_DEVICE (self));
nm_log_info (LOGD_DEVICE | LOGD_HW,
"(%s): found s390 '%s' subchannels [%s]",
iface, driver ? driver : "(unknown driver)", priv->subchannels);
out:
if (parent)
g_object_unref (parent);
if (dev)
g_object_unref (dev);
g_object_unref (client);
}
static GObject*
constructor (GType type,
guint n_construct_params,
@ -314,6 +426,9 @@ constructor (GType type,
nm_device_get_iface (NM_DEVICE (self)),
nm_device_get_ifindex (NM_DEVICE (self)));
/* s390 stuff */
_update_s390_subchannels (NM_DEVICE_ETHERNET (self));
caps = nm_device_get_capabilities (self);
if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
GError *error = NULL;
@ -1587,6 +1702,41 @@ real_deactivate_quickly (NMDevice *device)
_set_hw_addr (self, priv->perm_hw_addr, "reset");
}
static gboolean
match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
const GPtrArray *subchans;
int i;
*try_mac = TRUE;
subchans = nm_setting_wired_get_s390_subchannels (s_wired);
if (!subchans)
return TRUE;
/* connection requires subchannels but the device has none */
if (!priv->subchannels)
return FALSE;
/* Make sure each subchannel in the connection is a subchannel of this device */
for (i = 0; i < subchans->len; i++) {
const char *candidate = g_ptr_array_index (subchans, i);
gboolean found = FALSE;
if ( (priv->subchan1 && !strcmp (priv->subchan1, candidate))
|| (priv->subchan2 && !strcmp (priv->subchan2, candidate))
|| (priv->subchan3 && !strcmp (priv->subchan3, candidate)))
found = TRUE;
if (!found)
return FALSE;
}
*try_mac = FALSE;
return TRUE;
}
static gboolean
real_check_connection_compatible (NMDevice *device,
NMConnection *connection,
@ -1598,6 +1748,8 @@ real_check_connection_compatible (NMDevice *device,
NMSettingWired *s_wired;
const char *connection_type;
gboolean is_pppoe = FALSE;
const GByteArray *mac;
gboolean try_mac = TRUE;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
g_assert (s_con);
@ -1624,10 +1776,15 @@ real_check_connection_compatible (NMDevice *device,
}
if (s_wired) {
const GByteArray *mac;
if (!match_subchans (self, s_wired, &try_mac)) {
g_set_error (error,
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE,
"The connection's s390 subchannels did not match this device.");
return FALSE;
}
mac = nm_setting_wired_get_mac_address (s_wired);
if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) {
if (try_mac && mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) {
g_set_error (error,
NM_ETHERNET_ERROR, NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE,
"The connection's MAC address did not match this device.");
@ -1651,6 +1808,9 @@ spec_match_list (NMDevice *device, const GSList *specs)
matched = nm_match_spec_hwaddr (specs, hwaddr);
g_free (hwaddr);
if (!matched && priv->subchannels)
matched = nm_match_spec_s390_subchannels (specs, priv->subchannels);
return matched;
}
@ -1660,14 +1820,18 @@ wired_match_config (NMDevice *self, NMConnection *connection)
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMSettingWired *s_wired;
const GByteArray *s_ether;
gboolean try_mac = TRUE;
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired)
return FALSE;
if (!match_subchans (NM_DEVICE_ETHERNET (self), s_wired, &try_mac))
return FALSE;
/* MAC address check */
s_ether = nm_setting_wired_get_mac_address (s_wired);
if (s_ether && memcmp (s_ether->data, priv->perm_hw_addr, ETH_ALEN))
if (try_mac && s_ether && memcmp (s_ether->data, priv->perm_hw_addr, ETH_ALEN))
return FALSE;
return TRUE;
@ -1875,6 +2039,11 @@ dispose (GObject *object)
priv->monitor = NULL;
}
g_free (priv->subchan1);
g_free (priv->subchan2);
g_free (priv->subchan3);
g_free (priv->subchannels);
G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
}

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2008 Red Hat, Inc.
* Copyright (C) 2007 - 2010 Red Hat, Inc.
* Copyright (C) 2008 Novell, Inc.
*/
@ -107,6 +107,12 @@ struct _NMSystemConfigInterface {
*
* Method: mac Data: device MAC address formatted with leading zeros and
* lowercase letters, like 00:0a:0b:0c:0d:0e
*
* Method: s390-subchannels Data: string of 2 or 3 s390 subchannels
* separated by commas (,) that identify the
* device, like "0.0.09a0,0.0.09a1,0.0.09a2".
* The string may contain only the following
* characters: [a-fA-F0-9,.]
*/
GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config);

View file

@ -2941,6 +2941,7 @@ make_wired_setting (shvarFile *ifcfg,
char *value = NULL;
int mtu;
GByteArray *mac = NULL;
char *nettype;
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
@ -2968,15 +2969,98 @@ make_wired_setting (shvarFile *ifcfg,
}
g_byte_array_free (mac, TRUE);
} else if (!nm_controlled) {
/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
* the user that the device cannot be unmanaged.
*/
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
}
} else {
g_object_unref (s_wired);
s_wired = NULL;
return NULL;
}
value = svGetValue (ifcfg, "SUBCHANNELS", FALSE);
if (value) {
const char *p = value;
gboolean success = TRUE;
char **chans = NULL;
/* basic sanity checks */
while (*p) {
if (!isxdigit (*p) && (*p != ',') && (*p != '.')) {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid SUBCHANNELS '%s'", value);
success = FALSE;
break;
}
p++;
}
if (success) {
guint32 num_chans;
chans = g_strsplit_set (value, ",", 0);
num_chans = g_strv_length (chans);
if (num_chans < 2 || num_chans > 3) {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid SUBCHANNELS '%s' (%d channels, 2 or 3 expected)",
value, g_strv_length (chans));
} else {
GPtrArray *array = g_ptr_array_sized_new (num_chans);
g_ptr_array_add (array, chans[0]);
g_ptr_array_add (array, chans[1]);
if (num_chans == 3)
g_ptr_array_add (array, chans[2]);
g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, array, NULL);
g_ptr_array_free (array, TRUE);
/* set the unmanaged spec too */
if (!nm_controlled && !*unmanaged)
*unmanaged = g_strdup_printf ("s390-subchannels:%s", value);
}
g_strfreev (chans);
}
g_free (value);
}
value = svGetValue (ifcfg, "PORTNAME", FALSE);
if (value && strlen (value)) {
nm_setting_wired_add_s390_option (s_wired, "portname", value);
}
g_free (value);
nettype = svGetValue (ifcfg, "NETTYPE", FALSE);
if (nettype && strlen (nettype)) {
if (!strcmp (nettype, "qeth") || !strcmp (nettype, "lcs") || !strcmp (nettype, "ctc"))
g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, NULL);
else
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: unknown s390 NETTYPE '%s'", nettype);
}
value = svGetValue (ifcfg, "OPTIONS", FALSE);
if (value && strlen (value)) {
char **options, **iter;
iter = options = g_strsplit_set (value, " ", 0);
while (iter && *iter) {
char *equals = strchr (*iter, '=');
gboolean valid = FALSE;
if (equals) {
*equals = '\0';
valid = nm_setting_wired_add_s390_option (s_wired, *iter, equals + 1);
}
if (!valid)
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: invalid s390 OPTION '%s'", *iter);
iter++;
}
g_strfreev (options);
}
g_free (value);
g_free (nettype);
if (!nm_controlled && !*unmanaged) {
/* If NM_CONTROLLED=no but there wasn't a MAC address or z/VM
* subchannels, notify the user that the device cannot be unmanaged.
*/
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR or SUBCHANNELS was missing; device will be managed");
}
mac = NULL;

View file

@ -64,7 +64,8 @@ EXTRA_DIST = \
ifcfg-test-wifi-wep-40-ascii \
keys-test-wifi-wep-40-ascii \
ifcfg-test-wifi-wep-104-ascii \
keys-test-wifi-wep-104-ascii
keys-test-wifi-wep-104-ascii \
ifcfg-test-wired-qeth-static
check-local:
@for f in $(EXTRA_DIST); do \

View file

@ -0,0 +1,13 @@
# IBM QETH
DEVICE=eth1
BOOTPROTO=static
IPADDR=192.168.70.87
NETMASK=255.255.255.0
ONBOOT=yes
NETTYPE=qeth
SUBCHANNELS=0.0.0600,0.0.0601,0.0.0602
TYPE=Ethernet
PORTNAME=OSAPORT
OPTIONS='layer2=1 portno=0'
MACADDR=02:00:00:23:65:1a

View file

@ -5346,6 +5346,178 @@ test_read_wifi_wep_eap_ttls_chap (void)
g_object_unref (connection);
}
#define TEST_IFCFG_WIRED_QETH_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-qeth-static"
static void
test_read_wired_qeth_static (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
char *unmanaged = NULL;
char *keyfile = NULL;
char *routefile = NULL;
char *route6file = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const char *expected_id = "System test-wired-qeth-static";
const GByteArray *array;
const char *expected_channel0 = "0.0.0600";
const char *expected_channel1 = "0.0.0601";
const char *expected_channel2 = "0.0.0602";
const GPtrArray *subchannels;
connection = connection_from_file (TEST_IFCFG_WIRED_QETH_STATIC,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&routefile,
&route6file,
&error,
&ignore_error);
ASSERT (connection != NULL,
"wired-qeth-static-read", "failed to read %s: %s", TEST_IFCFG_WIRED_QETH_STATIC, error->message);
ASSERT (nm_connection_verify (connection, &error),
"wired-qeth-static-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_QETH_STATIC, error->message);
ASSERT (unmanaged == FALSE,
"wired-qeth-static-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_QETH_STATIC);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"wired-qeth-static-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"wired-qeth-static-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"wired-qeth-static-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* ===== WIRED SETTING ===== */
s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED));
ASSERT (s_wired != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* MAC address */
array = nm_setting_wired_get_mac_address (s_wired);
ASSERT (array == NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s / %s key",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS);
/* Subchannels */
subchannels = nm_setting_wired_get_s390_subchannels (s_wired);
ASSERT (subchannels != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_S390_SUBCHANNELS);
ASSERT (subchannels->len == 3,
"wired-qeth-static-verify-wired", "failed to verify %s: invalid %s / %s key (not 3 elements)",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_S390_SUBCHANNELS);
tmp = (const char *) g_ptr_array_index (subchannels, 0);
ASSERT (strcmp (tmp, expected_channel0) == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #0",
TEST_IFCFG_WIRED_QETH_STATIC);
tmp = (const char *) g_ptr_array_index (subchannels, 1);
ASSERT (strcmp (tmp, expected_channel1) == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #1",
TEST_IFCFG_WIRED_QETH_STATIC);
tmp = (const char *) g_ptr_array_index (subchannels, 2);
ASSERT (strcmp (tmp, expected_channel2) == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected subchannel #2",
TEST_IFCFG_WIRED_QETH_STATIC);
/* Nettype */
tmp = nm_setting_wired_get_s390_nettype (s_wired);
ASSERT (tmp != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_S390_NETTYPE);
ASSERT (strcmp (tmp, "qeth") == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_S390_NETTYPE);
/* port name */
tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "portname");
ASSERT (tmp != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'portname'",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
ASSERT (strcmp (tmp, "OSAPORT") == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'portname' value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* port number */
tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "portno");
ASSERT (tmp != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'portno'",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
ASSERT (strcmp (tmp, "0") == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'portno' value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* layer */
tmp = nm_setting_wired_get_s390_option_by_key (s_wired, "layer2");
ASSERT (tmp != NULL,
"wired-qeth-static-verify-wired", "failed to verify %s: missing %s s390 option 'layer2'",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
ASSERT (strcmp (tmp, "1") == 0,
"wired-qeth-static-verify-wired", "failed to verify %s: unexpected %s s390 option 'layer2' value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_WIRED_SETTING_NAME);
/* ===== IPv4 SETTING ===== */
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG));
ASSERT (s_ip4 != NULL,
"wired-qeth-static-verify-ip4", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip4_config_get_method (s_ip4);
ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
"wired-qeth-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIRED_QETH_STATIC,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_METHOD);
g_object_unref (connection);
}
static void
test_write_wired_static (void)
{
@ -8714,6 +8886,140 @@ test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
name, "unexpectedly able to read %s", TEST_IFCFG_IBFT_STATIC);
}
static void
test_write_wired_qeth_dhcp (void)
{
NMConnection *connection;
NMConnection *reread;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
char *uuid;
GPtrArray *subchans;
gboolean success;
GError *error = NULL;
char *testfile = NULL;
char *unmanaged = NULL;
char *keyfile = NULL;
char *routefile = NULL;
char *route6file = NULL;
gboolean ignore_error = FALSE;
connection = nm_connection_new ();
ASSERT (connection != NULL,
"wired-qeth-dhcp-write", "failed to allocate new connection");
/* Connection setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
ASSERT (s_con != NULL,
"wired-qeth-dhcp-write", "failed to allocate new %s setting",
NM_SETTING_CONNECTION_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_con));
uuid = nm_utils_uuid_generate ();
g_object_set (s_con,
NM_SETTING_CONNECTION_ID, "Test Write Wired qeth Static",
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
NULL);
g_free (uuid);
/* Wired setting */
s_wired = (NMSettingWired *) nm_setting_wired_new ();
ASSERT (s_wired != NULL,
"wired-qeth-dhcp-write", "failed to allocate new %s setting",
NM_SETTING_WIRED_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_wired));
subchans = g_ptr_array_sized_new (3);
g_ptr_array_add (subchans, "0.0.600");
g_ptr_array_add (subchans, "0.0.601");
g_ptr_array_add (subchans, "0.0.602");
g_object_set (s_wired,
NM_SETTING_WIRED_S390_SUBCHANNELS, subchans,
NM_SETTING_WIRED_S390_NETTYPE, "qeth",
NULL);
g_ptr_array_free (subchans, TRUE);
nm_setting_wired_add_s390_option (s_wired, "portname", "FOOBAR");
nm_setting_wired_add_s390_option (s_wired, "portno", "1");
nm_setting_wired_add_s390_option (s_wired, "layer2", "0");
nm_setting_wired_add_s390_option (s_wired, "protocol", "blahbalh");
/* IP4 setting */
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
ASSERT (s_ip4 != NULL,
"wired-qeth-dhcp-write", "failed to allocate new %s setting",
NM_SETTING_IP4_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
NULL);
/* IP6 setting */
s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
ASSERT (s_ip6 != NULL,
"wired-qeth-dhcp-write", "failed to allocate new %s setting",
NM_SETTING_IP6_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
g_object_set (s_ip6,
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
NULL);
/* Verify */
ASSERT (nm_connection_verify (connection, &error) == TRUE,
"wired-qeth-dhcp-write", "failed to verify connection: %s",
(error && error->message) ? error->message : "(unknown)");
/* Save the ifcfg */
success = writer_new_connection (connection,
TEST_SCRATCH_DIR "/network-scripts/",
&testfile,
&error);
ASSERT (success == TRUE,
"wired-qeth-dhcp-write", "failed to write connection to disk: %s",
(error && error->message) ? error->message : "(unknown)");
ASSERT (testfile != NULL,
"wired-qeth-dhcp-write", "didn't get ifcfg file path back after writing connection");
/* re-read the connection for comparison */
reread = connection_from_file (testfile,
NULL,
TYPE_ETHERNET,
NULL,
&unmanaged,
&keyfile,
&routefile,
&route6file,
&error,
&ignore_error);
unlink (testfile);
ASSERT (reread != NULL,
"wired-qeth-dhcp-write-reread", "failed to read %s: %s", testfile, error->message);
ASSERT (nm_connection_verify (reread, &error),
"wired-qeth-dhcp-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
"wired-qeth-dhcp-write", "written and re-read connection weren't the same.");
if (route6file)
unlink (route6file);
g_free (testfile);
g_free (keyfile);
g_free (routefile);
g_free (route6file);
g_object_unref (connection);
g_object_unref (reread);
}
static void
test_write_wired_pppoe (void)
{
@ -9038,6 +9344,7 @@ int main (int argc, char **argv)
test_read_wifi_wpa_eap_tls ();
test_read_wifi_wpa_eap_ttls_tls ();
test_read_wifi_wep_eap_ttls_chap ();
test_read_wired_qeth_static ();
test_write_wired_static ();
test_write_wired_static_ip6_only ();
@ -9087,6 +9394,7 @@ int main (int argc, char **argv)
test_write_wifi_wpa_eap_tls ();
test_write_wifi_wpa_eap_ttls_tls ();
test_write_wifi_wpa_eap_ttls_mschapv2 ();
test_write_wired_qeth_dhcp ();
/* iSCSI / ibft */
test_read_ibft_dhcp ();

View file

@ -842,7 +842,10 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
NMSettingWired *s_wired;
const GByteArray *device_mac, *cloned_mac;
char *tmp;
guint32 mtu;
const char *nettype, *portname, *s390_key, *s390_val;
guint32 mtu, num_opts, i;
const GPtrArray *s390_subchannels;
GString *str;
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired) {
@ -851,6 +854,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
return FALSE;
}
svSetValue (ifcfg, "HWADDR", NULL, FALSE);
device_mac = nm_setting_wired_get_mac_address (s_wired);
if (device_mac) {
tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
@ -877,6 +881,53 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
g_free (tmp);
}
svSetValue (ifcfg, "SUBCHANNELS", NULL, FALSE);
s390_subchannels = nm_setting_wired_get_s390_subchannels (s_wired);
if (s390_subchannels) {
if (s390_subchannels->len == 2) {
tmp = g_strdup_printf ("%s,%s",
(const char *) g_ptr_array_index (s390_subchannels, 0),
(const char *) g_ptr_array_index (s390_subchannels, 1));
} else if (s390_subchannels->len == 3) {
tmp = g_strdup_printf ("%s,%s,%s",
(const char *) g_ptr_array_index (s390_subchannels, 0),
(const char *) g_ptr_array_index (s390_subchannels, 1),
(const char *) g_ptr_array_index (s390_subchannels, 2));
}
svSetValue (ifcfg, "SUBCHANNELS", tmp, FALSE);
g_free (tmp);
}
svSetValue (ifcfg, "NETTYPE", NULL, FALSE);
nettype = nm_setting_wired_get_s390_nettype (s_wired);
if (nettype)
svSetValue (ifcfg, "NETTYPE", nettype, FALSE);
svSetValue (ifcfg, "PORTNAME", NULL, FALSE);
portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname");
if (portname)
svSetValue (ifcfg, "PORTNAME", portname, FALSE);
svSetValue (ifcfg, "OPTIONS", NULL, FALSE);
num_opts = nm_setting_wired_get_num_s390_options (s_wired);
if (s390_subchannels && num_opts) {
str = g_string_sized_new (30);
for (i = 0; i < num_opts; i++) {
nm_setting_wired_get_s390_option (s_wired, i, &s390_key, &s390_val);
/* portname is handled separately */
if (!strcmp (s390_key, "portname"))
continue;
if (str->len)
g_string_append_c (str, ' ');
g_string_append_printf (str, "%s=%s", s390_key, s390_val);
}
if (str->len)
svSetValue (ifcfg, "OPTIONS", str->str, FALSE);
g_string_free (str, TRUE);
}
svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE);
return TRUE;