summaryrefslogtreecommitdiff
path: root/libnm-util/nm-setting-ip4-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-util/nm-setting-ip4-config.c')
-rw-r--r--libnm-util/nm-setting-ip4-config.c125
1 files changed, 118 insertions, 7 deletions
diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c
index be819b1cac..d6574ca659 100644
--- a/libnm-util/nm-setting-ip4-config.c
+++ b/libnm-util/nm-setting-ip4-config.c
@@ -78,6 +78,7 @@ typedef struct {
GArray *dns; /* array of guint32; elements in network byte order */
GSList *dns_search; /* list of strings */
GSList *addresses; /* array of NMIP4Address */
+ GSList *address_labels; /* list of strings */
GSList *routes; /* array of NMIP4Route */
gboolean ignore_auto_routes;
gboolean ignore_auto_dns;
@@ -94,6 +95,7 @@ enum {
PROP_DNS,
PROP_DNS_SEARCH,
PROP_ADDRESSES,
+ PROP_ADDRESS_LABELS,
PROP_ROUTES,
PROP_IGNORE_AUTO_ROUTES,
PROP_IGNORE_AUTO_DNS,
@@ -440,6 +442,19 @@ nm_setting_ip4_config_get_address (NMSettingIP4Config *setting, guint32 i)
return (NMIP4Address *) g_slist_nth_data (priv->addresses, i);
}
+const char *
+nm_setting_ip4_config_get_address_label (NMSettingIP4Config *setting, guint32 i)
+{
+ NMSettingIP4ConfigPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+
+ priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->address_labels), NULL);
+
+ return (const char *) g_slist_nth_data (priv->address_labels, i);
+}
+
/**
* nm_setting_ip4_config_add_address:
* @setting: the #NMSettingIP4Config
@@ -455,6 +470,14 @@ gboolean
nm_setting_ip4_config_add_address (NMSettingIP4Config *setting,
NMIP4Address *address)
{
+ return nm_setting_ip4_config_add_address_with_label (setting, address, NULL);
+}
+
+gboolean
+nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *setting,
+ NMIP4Address *address,
+ const char *label)
+{
NMSettingIP4ConfigPrivate *priv;
NMIP4Address *copy;
GSList *iter;
@@ -472,6 +495,8 @@ nm_setting_ip4_config_add_address (NMSettingIP4Config *setting,
g_return_val_if_fail (copy != NULL, FALSE);
priv->addresses = g_slist_append (priv->addresses, copy);
+ priv->address_labels = g_slist_append (priv->address_labels, g_strdup (label));
+
g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
return TRUE;
}
@@ -487,16 +512,21 @@ void
nm_setting_ip4_config_remove_address (NMSettingIP4Config *setting, guint32 i)
{
NMSettingIP4ConfigPrivate *priv;
- GSList *elt;
+ GSList *addr, *label;
g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
- elt = g_slist_nth (priv->addresses, i);
- g_return_if_fail (elt != NULL);
+ addr = g_slist_nth (priv->addresses, i);
+ label = g_slist_nth (priv->address_labels, i);
+ g_return_if_fail (addr != NULL && label != NULL);
+
+ nm_ip4_address_unref ((NMIP4Address *) addr->data);
+ priv->addresses = g_slist_delete_link (priv->addresses, addr);
+ if (label->data)
+ g_free (label->data);
+ priv->address_labels = g_slist_delete_link (priv->address_labels, label);
- nm_ip4_address_unref ((NMIP4Address *) elt->data);
- priv->addresses = g_slist_delete_link (priv->addresses, elt);
g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
}
@@ -548,6 +578,8 @@ nm_setting_ip4_config_clear_addresses (NMSettingIP4Config *setting)
g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
priv->addresses = NULL;
+ g_slist_free_full (priv->address_labels, g_free);
+ priv->address_labels = NULL;
g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
}
@@ -822,10 +854,34 @@ nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting)
}
static gboolean
+verify_label (const char *label)
+{
+ const char *p;
+ char *iface;
+
+ p = strchr (label, ':');
+ if (!p)
+ return FALSE;
+ iface = g_strndup (label, p - label);
+ if (!nm_utils_iface_valid_name (iface)) {
+ g_free (iface);
+ return FALSE;
+ }
+ g_free (iface);
+
+ for (p++; *p; p++) {
+ if (!g_ascii_isalnum (*p) && *p != '_')
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
- GSList *iter;
+ GSList *iter, *l_iter;
int i;
if (!priv->method) {
@@ -912,8 +968,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
}
/* Validate addresses */
- for (iter = priv->addresses, i = 0; iter; iter = g_slist_next (iter), i++) {
+ for (iter = priv->addresses, l_iter = priv->address_labels, i = 0;
+ iter && l_iter;
+ iter = g_slist_next (iter), l_iter = g_slist_next (l_iter), i++) {
NMIP4Address *addr = (NMIP4Address *) iter->data;
+ const char *label = (const char *) l_iter->data;
guint32 prefix = nm_ip4_address_get_prefix (addr);
if (!nm_ip4_address_get_address (addr)) {
@@ -935,6 +994,27 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES);
return FALSE;
}
+
+ if (label && !verify_label (label)) {
+ g_set_error (error,
+ NM_SETTING_IP4_CONFIG_ERROR,
+ NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+ _("%d. IPv4 address has invalid label '%s'"),
+ i+1, label);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");
+ return FALSE;
+ }
+ }
+
+ if (iter || l_iter) {
+ g_set_error (error,
+ NM_SETTING_IP4_CONFIG_ERROR,
+ NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+ _("IPv4 address / label count mismatch (%d vs %d)"),
+ g_slist_length (priv->addresses),
+ g_slist_length (priv->address_labels));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");
+ return FALSE;
}
/* Validate routes */
@@ -990,6 +1070,7 @@ finalize (GObject *object)
g_slist_free_full (priv->dns_search, g_free);
g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
+ g_slist_free_full (priv->address_labels, g_free);
g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object);
@@ -1001,6 +1082,7 @@ set_property (GObject *object, guint prop_id,
{
NMSettingIP4Config *setting = NM_SETTING_IP4_CONFIG (object);
NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+ GSList *iter;
switch (prop_id) {
case PROP_METHOD:
@@ -1020,6 +1102,24 @@ set_property (GObject *object, guint prop_id,
case PROP_ADDRESSES:
g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
priv->addresses = nm_utils_ip4_addresses_from_gvalue (value);
+
+ if (g_slist_length (priv->addresses) != g_slist_length (priv->address_labels)) {
+ g_slist_free_full (priv->address_labels, g_free);
+ priv->address_labels = NULL;
+ for (iter = priv->addresses; iter; iter = iter->next)
+ priv->address_labels = g_slist_prepend (priv->address_labels, NULL);
+ }
+ break;
+ case PROP_ADDRESS_LABELS:
+ g_slist_free_full (priv->address_labels, g_free);
+ priv->address_labels = g_value_dup_boxed (value);
+ /* NULLs get converted to "" when this is sent over D-Bus. */
+ for (iter = priv->address_labels; iter; iter = iter->next) {
+ if (!g_strcmp0 (iter->data, "")) {
+ g_free (iter->data);
+ iter->data = NULL;
+ }
+ }
break;
case PROP_ROUTES:
g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
@@ -1074,6 +1174,9 @@ get_property (GObject *object, guint prop_id,
case PROP_ADDRESSES:
nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
break;
+ case PROP_ADDRESS_LABELS:
+ g_value_set_boxed (value, priv->address_labels);
+ break;
case PROP_ROUTES:
nm_utils_ip4_routes_to_gvalue (priv->routes, value);
break;
@@ -1239,6 +1342,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+ g_object_class_install_property
+ (object_class, PROP_ADDRESS_LABELS,
+ _nm_param_spec_specialized ("address-labels",
+ "Address labels",
+ "Internal use only",
+ DBUS_TYPE_G_LIST_OF_STRING,
+ G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+
/**
* NMSettingIP4Config:routes:
*