/** * nm_setting_bond_add_option: * @setting: the #NMSettingBond * @name: 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. Option names may contain only alphanumeric characters * (ie [a-zA-Z0-9]). Adding a new name replaces any existing name/value pair * that may already exist. * * The order of how to set several options is relevant because there are options * that conflict with each other. * * Returns: %TRUE if the option was valid and was added to the internal option * list, %FALSE if it was not. **/ gboolean nm_setting_bond_add_option (NMSettingBond *setting, const char *name, const char *value) { NMSettingBondPrivate *priv; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE); if (!value || !nm_setting_bond_validate_option (name, value)) return FALSE; priv = NM_SETTING_BOND_GET_PRIVATE (setting); g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value)); if ( !strcmp (name, NM_SETTING_BOND_OPTION_MIIMON) && strcmp (value, "0") != 0) { g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); } else if ( !strcmp (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL) && strcmp (value, "0") != 0) { g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_MIIMON); g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY); g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY); } g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS); return TRUE; }
/** * nm_setting_bond_get_option: * @setting: the #NMSettingBond * @idx: index of the desired option, from 0 to * nm_setting_bond_get_num_options() - 1 * @out_name: (out) (transfer none): on return, the name of the bonding option; * this value is owned by the setting and should not be modified * @out_value: (out) (transfer none): on return, the value of the name of the * bonding option; this value is owned by the setting and should not be * modified * * Given an index, return the value of the bonding option at that index. Indexes * are *not* guaranteed to be static across modifications to options done by * nm_setting_bond_add_option() and nm_setting_bond_remove_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_bond_get_option (NMSettingBond *setting, guint32 idx, const char **out_name, const char **out_value) { NMSettingBondPrivate *priv; GList *keys; const char *_key = NULL, *_value = NULL; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE); priv = NM_SETTING_BOND_GET_PRIVATE (setting); if (idx >= nm_setting_bond_get_num_options (setting)) return FALSE; keys = g_hash_table_get_keys (priv->options); _key = g_list_nth_data (keys, idx); _value = g_hash_table_lookup (priv->options, _key); if (out_name) *out_name = _key; if (out_value) *out_value = _value; g_list_free (keys); return TRUE; }
/** * nm_setting_bond_get_num_options: * @setting: the #NMSettingBond * * Returns the number of options that should be set for this bond when it * is activated. This can be used to retrieve each option individually * using nm_setting_bond_get_option(). * * Returns: the number of bonding options **/ guint32 nm_setting_bond_get_num_options (NMSettingBond *setting) { g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0); return g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (setting)->options); }
/** * nm_setting_bond_get_interface_name: * @setting: the #NMSettingBond * * Returns: the #NMSettingBond:interface-name property of the setting **/ const char * nm_setting_bond_get_interface_name (NMSettingBond *setting) { g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); return NM_SETTING_BOND_GET_PRIVATE (setting)->interface_name; }
static void finalize (GObject *object) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object); g_hash_table_destroy (priv->options); G_OBJECT_CLASS (nm_setting_bond_parent_class)->finalize (object); }
static gboolean compare_property (NMSetting *setting, NMSetting *other, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { NMSettingClass *parent_class; if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) { return options_equal (NM_SETTING_BOND (setting), NM_SETTING_BOND_GET_PRIVATE (setting)->options, NM_SETTING_BOND_GET_PRIVATE (other)->options); } /* Otherwise chain up to parent to handle generic compare */ parent_class = NM_SETTING_CLASS (nm_setting_bond_parent_class); return parent_class->compare_property (setting, other, prop_spec, flags); }
static void nm_setting_bond_init (NMSettingBond *setting) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); /* Default values: */ nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr"); }
/** * nm_setting_bond_get_option_by_name: * @setting: the #NMSettingBond * @name: the option name for which to retrieve the value * * Returns the value associated with the bonding option specified by * @name, 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_bond_get_option_by_name (NMSettingBond *setting, const char *name) { g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL); if (!nm_setting_bond_validate_option (name, NULL)) return NULL; return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object); switch (prop_id) { case PROP_OPTIONS: g_value_take_boxed (value, _nm_utils_copy_strdict (priv->options)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
/** * nm_setting_bond_remove_option: * @setting: the #NMSettingBond * @name: name of the option to remove * * Remove the bonding option referenced by @name 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_bond_remove_option (NMSettingBond *setting, const char *name) { gboolean found; g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE); if (!nm_setting_bond_validate_option (name, NULL)) return FALSE; found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name); if (found) g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS); return found; }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object); NMSettingBond *setting = NM_SETTING_BOND (object); switch (prop_id) { case PROP_INTERFACE_NAME: g_value_set_string (value, nm_setting_bond_get_interface_name (setting)); break; case PROP_OPTIONS: g_value_set_boxed (value, priv->options); 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) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object); GHashTable *new_hash; switch (prop_id) { case PROP_INTERFACE_NAME: g_free (priv->interface_name); priv->interface_name = g_value_dup_string (value); break; case PROP_OPTIONS: /* Must make a deep copy of the hash table here... */ g_hash_table_remove_all (priv->options); new_hash = g_value_get_boxed (value); if (new_hash) g_hash_table_foreach (new_hash, copy_hash, priv->options); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); GHashTableIter iter; const char *key, *value; int mode, miimon = 0, arp_interval = 0; int num_grat_arp = -1, num_unsol_na = -1; const char *mode_orig, *mode_new; const char *arp_ip_target = NULL; const char *lacp_rate; const char *primary; g_hash_table_iter_init (&iter, priv->options); while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) { if (!value[0] || !nm_setting_bond_validate_option (key, value)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("invalid option '%s' or its value '%s'"), key, value); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MIIMON); if (value) miimon = atoi (value); value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); if (value) arp_interval = atoi (value); value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP); if (value) num_grat_arp = atoi (value); value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); if (value) num_unsol_na = atoi (value); /* Can only set one of miimon and arp_interval */ if (miimon > 0 && arp_interval > 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("only one of '%s' and '%s' can be set"), NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } /* Verify bond mode */ mode_orig = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE); if (!mode_orig) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("mandatory option '%s' is missing"), NM_SETTING_BOND_OPTION_MODE); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } mode = nm_utils_bond_mode_string_to_int (mode_orig); if (mode == -1) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid value for '%s'"), value, NM_SETTING_BOND_OPTION_MODE); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } mode_new = nm_utils_bond_mode_int_to_string (mode); /* Make sure mode is compatible with other settings */ if ( strcmp (mode_new, "balance-alb") == 0 || strcmp (mode_new, "balance-tlb") == 0) { if (arp_interval > 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s=%s' is incompatible with '%s > 0'"), NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY); if (strcmp (mode_new, "active-backup") == 0) { if (primary && !nm_utils_iface_valid_name (primary)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid interface name for '%s' option"), primary, NM_SETTING_BOND_OPTION_PRIMARY); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } else { if (primary) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is only valid for '%s=%s'"), NM_SETTING_BOND_OPTION_PRIMARY, NM_SETTING_BOND_OPTION_MODE, "active-backup"); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (nm_connection_get_setting_infiniband (connection)) { if (strcmp (mode_new, "active-backup") != 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s=%s' is not a valid configuration for '%s'"), NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_INFINIBAND_SETTING_NAME); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (miimon == 0) { /* updelay and downdelay can only be used with miimon */ if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } /* arp_ip_target can only be used with arp_interval, and must * contain a comma-separated list of IPv4 addresses. */ arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (arp_interval > 0) { char **addrs; guint32 addr; int i; if (!arp_ip_target) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } addrs = g_strsplit (arp_ip_target, ",", -1); if (!addrs[0]) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is empty"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } for (i = 0; addrs[i]; i++) { if (!inet_pton (AF_INET, addrs[i], &addr)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' is not a valid IPv4 address for '%s' option"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } } g_strfreev (addrs); } else { if (arp_ip_target) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } lacp_rate = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE); if ( lacp_rate && g_strcmp0 (mode_new, "802.3ad") && strcmp (lacp_rate, "slow") != 0 && strcmp (lacp_rate, "0") != 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option is only valid with mode '%s'"), NM_SETTING_BOND_OPTION_LACP_RATE, "802.3ad"); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } if ( (num_grat_arp != -1 && num_unsol_na != -1) && (num_grat_arp != num_unsol_na)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' and '%s' cannot have different values"), NM_SETTING_BOND_OPTION_NUM_GRAT_ARP, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } if (!_nm_connection_verify_required_interface_name (connection, error)) return FALSE; /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */ if (g_strcmp0 (mode_orig, mode_new) != 0) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("'%s' option should be string"), NM_SETTING_BOND_OPTION_MODE); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return NM_SETTING_VERIFY_NORMALIZABLE; } return TRUE; }
static gboolean verify (NMSetting *setting, GSList *all_settings, GError **error) { NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting); GHashTableIter iter; const char *key, *value; const char *valid_modes[] = { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL }; int miimon = 0, arp_interval = 0; const char *arp_ip_target = NULL; const char *primary; if (!priv->interface_name || !strlen(priv->interface_name)) { g_set_error_literal (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_MISSING_PROPERTY, _("property is missing")); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME); return FALSE; } if (!nm_utils_iface_valid_name (priv->interface_name)) { g_set_error_literal (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_PROPERTY, _("property is invalid")); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME); return FALSE; } g_hash_table_iter_init (&iter, priv->options); while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) { if (!value[0] || !nm_setting_bond_validate_option (key, value)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("invalid option '%s' or its value '%s'"), key, value); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MIIMON); if (value) miimon = atoi (value); value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL); if (value) arp_interval = atoi (value); /* Can only set one of miimon and arp_interval */ if (miimon > 0 && arp_interval > 0) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("only one of '%s' and '%s' can be set"), NM_SETTING_BOND_OPTION_MIIMON, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); } value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE); if (!value) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_MISSING_OPTION, _("mandatory option '%s' is missing"), NM_SETTING_BOND_OPTION_MODE); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } if (!_nm_utils_string_in_list (value, valid_modes)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' is not a valid value for '%s'"), value, NM_SETTING_BOND_OPTION_MODE); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } /* Make sure mode is compatible with other settings */ if ( strcmp (value, "balance-alb") == 0 || strcmp (value, "balance-tlb") == 0) { if (arp_interval > 0) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s=%s' is incompatible with '%s > 0'"), NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY); if (strcmp (value, "active-backup") == 0) { if (primary && !nm_utils_iface_valid_name (primary)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' is not a valid interface name for '%s' option"), primary, NM_SETTING_BOND_OPTION_PRIMARY); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } else { if (primary) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' option is only valid for '%s=%s'"), NM_SETTING_BOND_OPTION_PRIMARY, NM_SETTING_BOND_OPTION_MODE, "active-backup"); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (nm_setting_find_in_list (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME)) { if (strcmp (value, "active-backup") != 0) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s=%s' is not a valid configuration for '%s'"), NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } if (miimon == 0) { /* updelay and downdelay can only be used with miimon */ if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } /* arp_ip_target can only be used with arp_interval, and must * contain a comma-separated list of IPv4 addresses. */ arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (arp_interval > 0) { char **addrs; guint32 addr; int i; if (!arp_ip_target) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_MISSING_OPTION, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } addrs = g_strsplit (arp_ip_target, ",", -1); if (!addrs[0]) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' option is empty"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } for (i = 0; addrs[i]; i++) { if (!inet_pton (AF_INET, addrs[i], &addr)) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' is not a valid IPv4 address for '%s' option"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); g_strfreev (addrs); return FALSE; } } g_strfreev (addrs); } else { if (arp_ip_target) { g_set_error (error, NM_SETTING_BOND_ERROR, NM_SETTING_BOND_ERROR_INVALID_OPTION, _("'%s' option requires '%s' option to be set"), NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL); g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS); return FALSE; } } return TRUE; }