summaryrefslogtreecommitdiff
path: root/libnm-util/nm-setting-bond.c
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2012-03-20 09:39:57 -0400
committerDan Winship <danw@gnome.org>2012-03-22 13:12:57 -0400
commitc4994bba5425e9c0ad84e8a7add2f3a95e577fde (patch)
tree687195600e95a4b8a4a6c456ba40e6adcb90c01c /libnm-util/nm-setting-bond.c
parent131b43405405bac2c3d2bd39f84774888841249c (diff)
downloadNetworkManager-c4994bba5425e9c0ad84e8a7add2f3a95e577fde.tar.gz
libnm-util: improve NMSettingBond:verify()
Add NM_SETTING_BOND_ERROR_INVALID_OPTION and NM_SETTING_BOND_ERROR_MISSING_OPTION error codes so we can better distinguish errors in different options, and add checks for various incompatible sets of options.
Diffstat (limited to 'libnm-util/nm-setting-bond.c')
-rw-r--r--libnm-util/nm-setting-bond.c136
1 files changed, 128 insertions, 8 deletions
diff --git a/libnm-util/nm-setting-bond.c b/libnm-util/nm-setting-bond.c
index 0e9bb0f452..9f9f438945 100644
--- a/libnm-util/nm-setting-bond.c
+++ b/libnm-util/nm-setting-bond.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <ctype.h>
+#include <stdlib.h>
#include <dbus/dbus-glib.h>
#include "nm-setting-bond.h"
@@ -353,6 +354,15 @@ dev_valid_name(const char *name)
return TRUE;
}
+static gint
+find_setting_by_name (gconstpointer a, gconstpointer b)
+{
+ NMSetting *setting = NM_SETTING (a);
+ const char *str = (const char *) b;
+
+ return strcmp (nm_setting_get_name (setting), str);
+}
+
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
@@ -367,6 +377,8 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
"balance-tlb",
"balance-alb",
NULL };
+ int miimon = 0, arp_interval = 0;
+ const char *arp_ip_target = NULL;
if (!priv->interface_name || !strlen(priv->interface_name)) {
g_set_error (error,
@@ -388,24 +400,131 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
if ( !validate_option (key)
|| !value[0]
- || (strlen (value) > 200)) {
+ || (strlen (value) > 200)
+ || strchr (value, ' ')) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ key);
+ 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,
+ NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ }
+
+ 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,
+ NM_SETTING_BOND_OPTION_MODE);
+ 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,
+ NM_SETTING_BOND_OPTION_MODE);
+ 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,
+ NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ }
+ }
+ if (g_slist_find_custom (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME, find_setting_by_name)) {
+ if (strcmp (value, "active-backup") != 0) {
g_set_error (error,
NM_SETTING_BOND_ERROR,
- NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
- NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_OPTION_MODE);
return FALSE;
}
+ }
- if ( (g_strcmp0 (key, "mode") == 0)
- && !_nm_utils_string_in_list (value, valid_modes)) {
+ 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_PROPERTY,
- NM_SETTING_BOND_OPTIONS);
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_OPTION_UPDELAY);
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,
+ NM_SETTING_BOND_OPTION_DOWNDELAY);
+ 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;
- /* XXX: Validate arp-ip-target */
+ if (!arp_ip_target) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_MISSING_OPTION,
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ return FALSE;
+ }
+
+ addrs = g_strsplit (arp_ip_target, ",", -1);
+ if (!addrs[0]) {
+ g_strfreev (addrs);
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ return FALSE;
+ }
+
+ for (i = 0; addrs[i]; i++) {
+ if (!inet_pton (AF_INET, addrs[i], &addr)) {
+ g_strfreev (addrs);
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ return FALSE;
+ }
+ }
+ g_strfreev (addrs);
+ } else {
+ if (arp_ip_target) {
+ g_set_error (error,
+ NM_SETTING_BOND_ERROR,
+ NM_SETTING_BOND_ERROR_INVALID_OPTION,
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ return FALSE;
+ }
}
return TRUE;
@@ -430,6 +549,7 @@ nm_setting_bond_init (NMSettingBond *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_add_option (setting, NM_SETTING_BOND_OPTION_MIIMON, "100");
}