Ejemplo n.º 1
0
static char *
get_virtual_iface_name (NMDeviceFactory *factory,
                        NMConnection *connection,
                        const char *parent_iface)
{
	const char *ifname;
	NMSettingVlan *s_vlan;

	g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME), NULL);

	s_vlan = nm_connection_get_setting_vlan (connection);
	g_assert (s_vlan);

	if (!parent_iface)
		return NULL;

	ifname = nm_connection_get_interface_name (connection);
	if (ifname)
		return g_strdup (ifname);

	/* If the connection doesn't specify the interface name for the VLAN
	 * device, we create one for it using the VLAN ID and the parent
	 * interface's name.
	 */
	return nm_utils_new_vlan_name (parent_iface, nm_setting_vlan_get_id (s_vlan));
}
Ejemplo n.º 2
0
NMDevice *
nm_device_vlan_new_for_connection (NMConnection *connection, NMDevice *parent)
{
	NMDevice *device;
	NMSettingVlan *s_vlan;
	char *iface;

	g_return_val_if_fail (connection != NULL, NULL);
	g_return_val_if_fail (NM_IS_DEVICE (parent), NULL);

	s_vlan = nm_connection_get_setting_vlan (connection);
	g_return_val_if_fail (s_vlan != NULL, NULL);

	iface = g_strdup (nm_connection_get_interface_name (connection));
	if (!iface) {
		iface = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
		                                nm_setting_vlan_get_id (s_vlan));
	}

	if (   !nm_platform_vlan_add (iface,
	                              nm_device_get_ifindex (parent),
	                              nm_setting_vlan_get_id (s_vlan),
	                              nm_setting_vlan_get_flags (s_vlan))
	    && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
		nm_log_warn (LOGD_DEVICE | LOGD_VLAN, "(%s) failed to add VLAN interface for '%s'",
		             iface, nm_connection_get_id (connection));
		g_free (iface);
		return NULL;
	}

	device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
	                                    NM_DEVICE_IFACE, iface,
	                                    NM_DEVICE_VLAN_PARENT, parent,
	                                    NM_DEVICE_DRIVER, "8021q",
	                                    NM_DEVICE_TYPE_DESC, "VLAN",
	                                    NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
	                                    NULL);
	g_free (iface);
	if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) {
		g_object_unref (device);
		device = NULL;
	}

	return device;
}
Ejemplo n.º 3
0
static gboolean
connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
	NMSettingConnection *s_con;
	NMSettingVlan *s_vlan;
	NMSettingWired *s_wired;
	const char *ctype, *dev_iface_name, *vlan_iface_name;
	const GByteArray *mac_address;
	char *mac_address_str;

	s_con = nm_connection_get_setting_connection (connection);
	g_assert (s_con);

	ctype = nm_setting_connection_get_connection_type (s_con);
	if (strcmp (ctype, NM_SETTING_VLAN_SETTING_NAME) != 0) {
		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_NOT_VLAN_CONNECTION,
		             "The connection was not a VLAN connection.");
		return FALSE;
	}

	s_vlan = nm_connection_get_setting_vlan (connection);
	if (!s_vlan) {
		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INVALID_VLAN_CONNECTION,
		             "The connection was not a valid VLAN connection.");
		return FALSE;
	}

	if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) {
		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_ID_MISMATCH,
		             "The VLAN identifiers of the device and the connection didn't match.");
		return FALSE;
	}

	dev_iface_name = nm_device_get_iface (device);
	vlan_iface_name = nm_setting_vlan_get_interface_name (s_vlan);
	if (vlan_iface_name && g_strcmp0 (dev_iface_name, vlan_iface_name) != 0) {
		g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_INTERFACE_MISMATCH,
		             "The interfaces of the device and the connection didn't match.");
		return FALSE;
	}

	s_wired = nm_connection_get_setting_wired (connection);
	if (s_wired)
		mac_address = nm_setting_wired_get_mac_address (s_wired);
	else
		mac_address = NULL;
	if (mac_address) {
		mac_address_str = nm_utils_hwaddr_ntoa_len (mac_address->data, mac_address->len);
		if (!g_strcmp0 (mac_address_str, NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address)) {
			g_set_error (error, NM_DEVICE_VLAN_ERROR, NM_DEVICE_VLAN_ERROR_MAC_MISMATCH,
			             "The hardware address of the device and the connection didn't match.");
		}
		g_free (mac_address_str);
	}

	return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error);
}
Ejemplo n.º 4
0
static void
update_connection (NMDevice *device, NMConnection *connection)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (device);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
	NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection);
	int ifindex = nm_device_get_ifindex (device);
	int parent_ifindex = -1, vlan_id = -1;
	NMDevice *parent;
	const char *setting_parent, *new_parent;

	if (!s_vlan) {
		s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
		nm_connection_add_setting (connection, (NMSetting *) s_vlan);
	}

	if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) {
		_LOGW (LOGD_VLAN, "failed to get VLAN interface info while updating connection.");
		return;
	}

	if (priv->vlan_id != vlan_id) {
		priv->vlan_id = vlan_id;
		g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID);
	}

	if (vlan_id != nm_setting_vlan_get_id (s_vlan))
		g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL);

	if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS)
		parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
	else
		parent = NULL;
	nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent);

	/* Update parent in the connection; default to parent's interface name */
	if (parent) {
		new_parent = nm_device_get_iface (parent);
		setting_parent = nm_setting_vlan_get_parent (s_vlan);
		if (setting_parent && nm_utils_is_uuid (setting_parent)) {
			NMConnection *parent_connection;

			/* Don't change a parent specified by UUID if it's still valid */
			parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent);
			if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection))
				new_parent = NULL;
		}
		if (new_parent)
			g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL);
	} else
		g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL);
}
Ejemplo n.º 5
0
static gboolean
create_and_realize (NMDevice *device,
                    NMConnection *connection,
                    NMDevice *parent,
                    NMPlatformLink *out_plink,
                    GError **error)
{
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
	const char *iface = nm_device_get_iface (device);
	NMSettingVlan *s_vlan;
	int parent_ifindex, vlan_id;
	NMPlatformError plerr;

	g_assert (out_plink);

	s_vlan = nm_connection_get_setting_vlan (connection);
	g_assert (s_vlan);

	if (!nm_device_supports_vlans (parent)) {
		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
		             "no support for VLANs on interface %s of type %s",
		             nm_device_get_iface (parent),
		             nm_device_get_type_desc (parent));
		return FALSE;
	}

	parent_ifindex = nm_device_get_ifindex (parent);
	g_warn_if_fail (parent_ifindex > 0);

	vlan_id = nm_setting_vlan_get_id (s_vlan);

	plerr = nm_platform_vlan_add (NM_PLATFORM_GET,
	                              iface,
	                              parent_ifindex,
	                              vlan_id,
	                              nm_setting_vlan_get_flags (s_vlan),
	                              out_plink);
	if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
		             "Failed to create VLAN interface '%s' for '%s': %s",
		             iface,
		             nm_connection_get_id (connection),
		             nm_platform_error_to_string (plerr));
		return FALSE;
	}

	g_warn_if_fail (priv->parent == NULL);
	nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent);
	priv->vlan_id = vlan_id;

	return TRUE;
}
Ejemplo n.º 6
0
static void
vlan_settings_changed (GObject    *object,
                       GParamSpec *pspec,
                       gpointer    user_data)
{
	NMEditorVlanWidgetBinding *binding = user_data;
	const char *ifname, *parent;
	char *ifname_parent;
	int ifname_id, id;

	if (binding->updating)
		return;

	ifname = nm_setting_connection_get_interface_name (binding->s_con);
	parent = nm_setting_vlan_get_parent (binding->s_vlan);
	id = nm_setting_vlan_get_id (binding->s_vlan);

	if (!parse_interface_name (ifname, &ifname_parent, &ifname_id))
		return;

	/* If the id in INTERFACE_NAME changed, and ID is either unset, or was previously
	 * in sync with INTERFACE_NAME, then update ID.
	 */
	if (   id != ifname_id
	    && (id == binding->last_ifname_id || id == 0)) {
		binding->updating = TRUE;
		g_object_set (G_OBJECT (binding->s_vlan),
		              NM_SETTING_VLAN_ID, ifname_id,
		              NULL);
		binding->updating = FALSE;
	}

	/* If the PARENT in INTERFACE_NAME changed, and PARENT is either unset, or was
	 * previously in sync with INTERFACE_NAME, then update PARENT.
	 */
	if (   g_strcmp0 (parent, ifname_parent) != 0
	    && (   g_strcmp0 (parent, binding->last_ifname_parent) == 0
	        || !parent || !*parent)) {
		binding->updating = TRUE;
		g_object_set (G_OBJECT (binding->s_vlan),
		              NM_SETTING_VLAN_PARENT, ifname_parent,
		              NULL);
		binding->updating = FALSE;
	}

	g_free (binding->last_ifname_parent);
	binding->last_ifname_parent = ifname_parent;
	binding->last_ifname_id = ifname_id;
}
Ejemplo n.º 7
0
static gboolean
connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
	NMDeviceVlanPrivate *priv;
	NMSettingVlan *s_vlan;
	NMSettingWired *s_wired;
	const char *setting_hwaddr;

	if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error))
		return FALSE;

	if (!nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) {
		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
		                     _("The connection was not a VLAN connection."));
		return FALSE;
	}

	s_vlan = nm_connection_get_setting_vlan (connection);
	if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) {
		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
		                     _("The VLAN identifiers of the device and the connection didn't match."));
		return FALSE;
	}

	s_wired = nm_connection_get_setting_wired (connection);
	if (s_wired)
		setting_hwaddr = nm_setting_wired_get_mac_address (s_wired);
	else
		setting_hwaddr = NULL;
	if (setting_hwaddr) {
		priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
		if (   !priv->hw_address
		    || !nm_utils_hwaddr_matches (setting_hwaddr, -1,
		                                 priv->hw_address, -1)) {
			g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
			                     _("The hardware address of the device and the connection didn't match."));
		}
	}

	return TRUE;
}
Ejemplo n.º 8
0
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
	NMSettingVlan *s_vlan;
	const char *parent, *iface = NULL;

	if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_compatible (device, connection))
		return FALSE;

	s_vlan = nm_connection_get_setting_vlan (connection);
	if (!s_vlan)
		return FALSE;

	if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
		return FALSE;

	/* Check parent interface; could be an interface name or a UUID */
	parent = nm_setting_vlan_get_parent (s_vlan);
	if (parent) {
		if (!match_parent (NM_DEVICE_VLAN (device), parent))
			return FALSE;
	} else {
		/* Parent could be a MAC address in an NMSettingWired */
		if (!match_hwaddr (device, connection, TRUE))
			return FALSE;
	}

	/* Ensure the interface name matches.  If not specified we assume a match
	 * since both the parent interface and the VLAN ID matched by the time we
	 * get here.
	 */
	iface = nm_connection_get_interface_name (connection);
	if (iface) {
		if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0)
			return FALSE;
	}

	return TRUE;
}
Ejemplo n.º 9
0
static void
populate_ui (CEPageVlan *self)
{
    CEPageVlanPrivate *priv = CE_PAGE_VLAN_GET_PRIVATE (self);
    GSList *devices, *d_iter;
    NMConnection *parent_connection = NULL;
    NMDevice *device, *parent_device = NULL;
    const char *parent, *iface, *current_parent;
    int i, mtu_def, mtu_val;

    devices = get_vlan_devices (self);

    /* Parent */
    build_vlan_parent_list (self, devices);

    parent = nm_setting_vlan_get_parent (priv->setting);
    if (parent) {
        /* UUID? */
        parent_connection = (NMConnection *)nm_remote_settings_get_connection_by_uuid (CE_PAGE (self)->settings, parent);
        if (!parent_connection) {
            /* Interface name? */
            for (d_iter = devices; d_iter; d_iter = d_iter->next) {
                device = d_iter->data;

                if (!g_strcmp0 (parent, nm_device_get_iface (device))) {
                    parent_device = device;
                    break;
                }
            }
        }
    }

    /* If NMSettingVlan:parent didn't indicate a device, but we have a
     * wired setting, figure out the device from that.
     */
    if (priv->s_hw && !parent_device) {
        const GByteArray *mac;
        const char *device_mac_str;
        char *mac_str;

        if (NM_IS_SETTING_WIRED (priv->s_hw))
            mac = nm_setting_wired_get_mac_address (NM_SETTING_WIRED (priv->s_hw));
        else
            mac = NULL;

        if (mac) {
            mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_ETHER);

            for (d_iter = devices; d_iter; d_iter = d_iter->next) {
                device = d_iter->data;

                if (NM_IS_DEVICE_ETHERNET (device))
                    device_mac_str = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
                else
                    device_mac_str = NULL;

                if (!g_strcmp0 (mac_str, device_mac_str)) {
                    parent_device = device;
                    break;
                }
            }
        }
    }

    current_parent = parent;
    if (parent_device || parent_connection) {
        for (i = 0; priv->parents[i]; i++) {
            if (parent_device && parent_device != priv->parents[i]->device)
                continue;
            if (parent_connection != priv->parents[i]->connection)
                continue;

            current_parent = priv->parents[i]->label;
            break;
        }
    }
    ce_page_setup_mac_combo (CE_PAGE (self), priv->parent, current_parent, priv->parent_labels);
    g_signal_connect (priv->parent, "changed", G_CALLBACK (parent_changed), self);

    if (current_parent)
        priv->last_parent = g_strndup (current_parent, strcspn (current_parent, " "));

    /* Name */
    iface = nm_setting_vlan_get_interface_name (priv->setting);
    if (iface)
        gtk_entry_set_text (priv->name_entry, iface);
    g_signal_connect (priv->name_entry, "changed", G_CALLBACK (name_changed), self);

    /* ID */
    priv->last_id = nm_setting_vlan_get_id (priv->setting);
    gtk_spin_button_set_value (priv->id_entry, priv->last_id);
    g_signal_connect (priv->id_entry, "value-changed", G_CALLBACK (id_changed), self);

    /* Cloned MAC address */
    if (NM_IS_SETTING_WIRED (priv->s_hw)) {
        ce_page_mac_to_entry (nm_setting_wired_get_cloned_mac_address (NM_SETTING_WIRED (priv->s_hw)),
                              ARPHRD_ETHER, priv->cloned_mac);
    }
    g_signal_connect (priv->cloned_mac, "changed", G_CALLBACK (stuff_changed), self);

    /* MTU */
    if (NM_IS_SETTING_WIRED (priv->s_hw)) {
        mtu_def = ce_get_property_default (priv->s_hw, NM_SETTING_WIRED_MTU);
        mtu_val = nm_setting_wired_get_mtu (NM_SETTING_WIRED (priv->s_hw));
    } else {
        mtu_def = mtu_val = 1500;
    }
    g_signal_connect (priv->mtu, "output",
                      G_CALLBACK (ce_spin_output_with_default),
                      GINT_TO_POINTER (mtu_def));

    gtk_spin_button_set_value (priv->mtu, (gdouble) mtu_val);
    g_signal_connect (priv->mtu, "value-changed", G_CALLBACK (stuff_changed), self);

    g_slist_free (devices);
}