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
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.º 3
0
static NMDevice *
find_vlan_parent (GSList *connections, NMApplet *applet)
{
	const GPtrArray *devices;
	NMDevice *parent_device;
	GSList *iter;

	devices = nm_client_get_devices (applet->nm_client);
	if (!devices)
		return NULL;

	for (iter = connections; iter; iter = iter->next) {
		NMConnection *connection = iter->data;
		NMSettingVlan *s_vlan;
		const char *parent;

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

		parent = nm_setting_vlan_get_parent (s_vlan);
		if (parent && nm_utils_iface_valid_name (parent)) {
			parent_device = find_device_by_iface (parent, devices);
		} else {
			NMSettingConnection *s_con;
			NMSetting *s_hw;
			const char *type;
			GByteArray *mac;

			s_con = nm_connection_get_setting_connection (connection);
			type = nm_setting_connection_get_connection_type (s_con);
			s_hw = nm_connection_get_setting_by_name (connection, type);
			if (!s_hw) {
				g_warn_if_reached ();
				continue;
			}

			if (!g_object_class_find_property (G_OBJECT_GET_CLASS (s_hw),
			                                   "mac-address"))
				continue;

			g_object_get (G_OBJECT (s_hw),
			              "mac-address", &mac,
			              NULL);
			if (mac) {
				parent_device = find_device_by_mac (mac, devices);
				g_byte_array_unref (mac);
			} else
				parent_device = NULL;
		}
		
		if (parent_device)
			return parent_device;
	}

	return NULL;
}
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 NMActStageReturn
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
	NMActRequest *req;
	NMConnection *connection;
	NMSettingVlan *s_vlan;
	NMSettingWired *s_wired;
	const char *cloned_mac;
	NMActStageReturn ret;

	g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);

	ret = NM_DEVICE_CLASS (nm_device_vlan_parent_class)->act_stage1_prepare (dev, reason);
	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
		return ret;

	req = nm_device_get_act_request (dev);
	g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);

	connection = nm_act_request_get_connection (req);
	g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);

	s_wired = nm_connection_get_setting_wired (connection);
	if (s_wired) {
		/* Set device MAC address if the connection wants to change it */
		cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
		if (cloned_mac)
			nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN);
	}

	s_vlan = nm_connection_get_setting_vlan (connection);
	if (s_vlan) {
		int ifindex = nm_device_get_ifindex (dev);
		int num, i;
		guint32 from, to;

		num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP);
		for (i = 0; i < num; i++) {
			if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to))
				nm_platform_vlan_set_ingress_map (ifindex, from, to);
		}
		num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP);
		for (i = 0; i < num; i++) {
			if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to))
				nm_platform_vlan_set_egress_map (ifindex, from, to);
		}
	}

	return ret;
}
Ejemplo n.º 7
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.º 8
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.º 9
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.º 10
0
CEPage *
ce_page_vlan_new (NMConnection *connection,
                  GtkWindow *parent_window,
                  NMClient *client,
                  NMRemoteSettings *settings,
                  const char **out_secrets_setting_name,
                  GError **error)
{
    CEPageVlan *self;
    CEPageVlanPrivate *priv;

    self = CE_PAGE_VLAN (ce_page_new (CE_TYPE_PAGE_VLAN,
                                      connection,
                                      parent_window,
                                      client,
                                      settings,
                                      UIDIR "/ce-page-vlan.ui",
                                      "VlanPage",
                                      _("VLAN")));
    if (!self) {
        g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load vlan user interface."));
        return NULL;
    }

    vlan_private_init (self);
    priv = CE_PAGE_VLAN_GET_PRIVATE (self);

    priv->setting = nm_connection_get_setting_vlan (connection);
    if (!priv->setting) {
        priv->setting = NM_SETTING_VLAN (nm_setting_vlan_new ());
        nm_connection_add_setting (connection, NM_SETTING (priv->setting));
    }
    priv->s_hw = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);

    g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);

    return CE_PAGE (self);
}
Ejemplo n.º 11
0
static const char *
get_connection_parent (NMDeviceFactory *factory, NMConnection *connection)
{
	NMSettingVlan *s_vlan;
	NMSettingWired *s_wired;
	const char *parent = NULL;

	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);

	parent = nm_setting_vlan_get_parent (s_vlan);
	if (parent)
		return parent;

	/* Try the hardware address from the VLAN connection's hardware setting */
	s_wired = nm_connection_get_setting_wired (connection);
	if (s_wired)
		return nm_setting_wired_get_mac_address (s_wired);

	return NULL;
}
Ejemplo n.º 12
0
static gboolean
complete_connection (NMDevice *device,
                     NMConnection *connection,
                     const char *specific_object,
                     const GSList *existing_connections,
                     GError **error)
{
	NMSettingVlan *s_vlan;

	nm_utils_complete_generic (connection,
	                           NM_SETTING_VLAN_SETTING_NAME,
	                           existing_connections,
	                           NULL,
	                           _("VLAN connection"),
	                           NULL,
	                           TRUE);

	s_vlan = nm_connection_get_setting_vlan (connection);
	if (!s_vlan) {
		g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID,
		                     "A 'vlan' setting is required.");
		return FALSE;
	}

	/* If there's no VLAN interface, no parent, and no hardware address in the
	 * settings, then there's not enough information to complete the setting.
	 */
	if (   !nm_setting_vlan_get_parent (s_vlan)
	    && !match_hwaddr (device, connection, TRUE)) {
		g_set_error_literal (error, NM_VLAN_ERROR, NM_VLAN_ERROR_CONNECTION_INVALID,
		                     "The 'vlan' setting had no interface name, parent, or hardware address.");
		return FALSE;
	}

	return TRUE;
}