device/bond: rework setting of arp_ip_target bond options

- the arp_ip_target option in the settings might not have normalized
  IP addresses or duplicates. If there would be duplicates, setting
  them twice would fail with EINVAL. Hence, first normalize them
  and make them unique.

- if what we want to set is identical to what is already set, don't
  do anything.

(cherry picked from commit 6a923a5d57)
This commit is contained in:
Thomas Haller
2020-06-30 15:33:10 +02:00
parent c284f3c7fa
commit 45c95e9314

View File

@@ -85,6 +85,16 @@ _set_bond_attr (NMDevice *device, const char *attr, const char *value)
return ret;
}
#define _set_bond_attr_take(device, attr, value) \
G_STMT_START { \
gs_free char *_tmp = (value); \
\
_set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, _tmp); \
} G_STMT_END
#define _set_bond_attr_printf(device, attr, fmt, ...) \
_set_bond_attr_take ((device), (attr), g_strdup_printf (fmt, __VA_ARGS__))
static gboolean
ignore_option (NMSettingBond *s_bond, const char *option, const char *value)
{
@@ -173,24 +183,61 @@ master_update_slave_connection (NMDevice *self,
static void
set_arp_targets (NMDevice *device,
NMBondMode mode,
const char *value,
const char *delim,
const char *prefix)
const char *cur_arp_ip_target,
const char *new_arp_ip_target)
{
gs_free const char **value_v = NULL;
gs_unref_ptrarray GPtrArray *free_list = NULL;
gs_free const char **cur_strv = NULL;
gs_free const char **new_strv = NULL;
gsize cur_len;
gsize new_len;
gsize i;
gsize j;
value_v = nm_utils_strsplit_set (value, delim);
if (!value_v)
return;
for (i = 0; value_v[i]; i++) {
gs_free char *tmp = NULL;
cur_strv = nm_utils_strsplit_set_full (cur_arp_ip_target, NM_ASCII_SPACES, NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
new_strv = nm_utils_bond_option_arp_ip_targets_split (new_arp_ip_target);
tmp = g_strdup_printf ("%s%s", prefix, value_v[i]);
_set_bond_attr (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, tmp);
cur_len = NM_PTRARRAY_LEN (cur_strv);
new_len = NM_PTRARRAY_LEN (new_strv);
if (new_len > 0) {
for (j = 0, i = 0; i < new_len; i++) {
const char *s;
in_addr_t a4;
s = new_strv[i];
if (nm_utils_parse_inaddr_bin (AF_INET, s, NULL, &a4)) {
char sbuf[INET_ADDRSTRLEN];
_nm_utils_inet4_ntop (a4, sbuf);
if (!nm_streq (s, sbuf)) {
if (!free_list)
free_list = g_ptr_array_new_with_free_func (g_free);
s = g_strdup (sbuf);
g_ptr_array_add (free_list, (gpointer) s);
}
}
if (nm_utils_strv_find_first ((char **) new_strv, i, s) < 0)
new_strv[j++] = s;
}
new_strv[j] = NULL;
new_len = j;
}
if ( cur_len == 0
&& new_len == 0)
return;
if (_nm_utils_strv_equal ((char **) cur_strv, (char **) new_strv))
return;
for (i = 0; i < cur_len; i++)
_set_bond_attr_printf (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "-%s", cur_strv[i]);
for (i = 0; i < new_len; i++)
_set_bond_attr_printf (device, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "+%s", new_strv[i]);
}
/*
* Sets bond attribute stored in the option hashtable or
* the default value if no value was set.
@@ -218,8 +265,7 @@ apply_bonding_config (NMDeviceBond *self)
NMSettingBond *s_bond;
NMBondMode mode;
const char *mode_str;
const char *value;
char *contents;
gs_free char *cur_arp_ip_target = NULL;
s_bond = nm_device_get_applied_setting (device, NM_TYPE_SETTING_BOND);
g_return_val_if_fail (s_bond, FALSE);
@@ -241,13 +287,13 @@ apply_bonding_config (NMDeviceBond *self)
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
/* ARP targets: clear and initialize the list */
contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
cur_arp_ip_target = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
ifindex,
NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
set_arp_targets (device, mode, contents, " \n", "-");
value = nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
set_arp_targets (device, mode, value, ",", "+");
g_free (contents);
set_arp_targets (device,
mode,
cur_arp_ip_target,
nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM);
set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);