예제 #1
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);
}
예제 #2
0
static void
dispose (GObject *object)
{
	nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), NULL);

	G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
}
예제 #3
0
static gboolean
component_added (NMDevice *device, GObject *component)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (device);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
	NMDevice *added_device;
	int parent_ifindex = -1;

	if (priv->parent)
		return FALSE;

	if (!NM_IS_DEVICE (component))
		return FALSE;
	added_device = NM_DEVICE (component);

	if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, nm_device_get_ifindex (device), &parent_ifindex, NULL)) {
		_LOGW (LOGD_VLAN, "failed to get VLAN interface info while checking added component.");
		return FALSE;
	}

	if (   parent_ifindex <= 0
	    || nm_device_get_ifindex (added_device) != parent_ifindex)
		return FALSE;

	nm_device_vlan_set_parent (self, added_device);

	/* Don't claim parent exclusively */
	return FALSE;
}
예제 #4
0
static void
get_property (GObject *object,
              guint prop_id,
              GValue *value,
              GParamSpec *pspec)
{
	NMDeviceVlan *device = NM_DEVICE_VLAN (object);

	_nm_object_ensure_inited (NM_OBJECT (object));

	switch (prop_id) {
	case PROP_HW_ADDRESS:
		g_value_set_string (value, nm_device_vlan_get_hw_address (device));
		break;
	case PROP_CARRIER:
		g_value_set_boolean (value, nm_device_vlan_get_carrier (device));
		break;
	case PROP_PARENT:
		g_value_set_object (value, nm_device_vlan_get_parent (device));
		break;
	case PROP_VLAN_ID:
		g_value_set_uint (value, nm_device_vlan_get_vlan_id (device));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
예제 #5
0
static void
deactivate (NMDevice *device)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (device);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);

	/* Reset MAC address back to initial address */
	nm_device_set_hw_addr (device, priv->initial_hw_addr, "reset", LOGD_VLAN);
}
예제 #6
0
static void
update_initial_hw_address (NMDevice *dev)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (dev);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);

	priv->initial_hw_addr = g_strdup (nm_device_get_hw_address (dev));
	_LOGD (LOGD_DEVICE | LOGD_VLAN, "read initial MAC address %s", priv->initial_hw_addr);
}
예제 #7
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);
}
예제 #8
0
static void
finalize (GObject *object)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (object);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);

	g_free (priv->initial_hw_addr);

	G_OBJECT_CLASS (nm_device_vlan_parent_class)->finalize (object);
}
예제 #9
0
static void
constructed (GObject *object)
{
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);

	G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object);

	priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_VLAN);
	register_properties (NM_DEVICE_VLAN (object));
}
예제 #10
0
static void
setup (NMDevice *device, NMPlatformLink *plink)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (device);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);

	NM_DEVICE_CLASS (nm_device_vlan_parent_class)->setup (device, plink);

	_LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s",
	       priv->vlan_id, nm_device_get_iface (priv->parent));
}
예제 #11
0
static void
vlan_add_menu_item (NMDevice *device,
                    gboolean multiple_devices,
                    GSList *connections,
                    NMConnection *active,
                    GtkWidget *menu,
                    NMApplet *applet)
{
	char *text;
	GtkWidget *item;
	gboolean carrier = TRUE;

	text = nma_utils_get_connection_device_name (connections->data);
	item = applet_menu_item_create_device_item_helper (device, applet, text);
	g_free (text);

	/* If the VLAN device exists, check its carrier */
	if (device && nm_device_get_capabilities (device) & NM_DEVICE_CAP_CARRIER_DETECT)
		carrier = nm_device_vlan_get_carrier (NM_DEVICE_VLAN (device));
	else {
		NMDevice *parent;

		/* If we can find its parent, check the parent's carrier */
		parent = find_vlan_parent (connections, applet);

		if (parent && nm_device_get_capabilities (parent) & NM_DEVICE_CAP_CARRIER_DETECT)
			g_object_get (G_OBJECT (parent), "carrier", &carrier, NULL);
	} /* else fall back to assuming carrier is present */		

	gtk_widget_set_sensitive (item, FALSE);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	gtk_widget_show (item);

	if (g_slist_length (connections))
		applet_add_connection_items (device, connections, carrier, active, NMA_ADD_ACTIVE, menu, applet);

	/* Notify user of unmanaged or unavailable device */
	if (device) {
		item = nma_menu_device_get_menu_item (device, applet, carrier ? NULL : _("disconnected"));
		if (item) {
			gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
			gtk_widget_show (item);
		}
	}

	if (!device || !nma_menu_device_check_unusable (device)) {
		if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
			applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"));

		if (g_slist_length (connections))
			applet_add_connection_items (device, connections, carrier, active, NMA_ADD_INACTIVE, menu, applet);
	}
}
예제 #12
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;
}
예제 #13
0
static void
parent_state_changed (NMDevice *parent,
                      NMDeviceState new_state,
                      NMDeviceState old_state,
                      NMDeviceStateReason reason,
                      gpointer user_data)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);

	/* We'll react to our own carrier state notifications. Ignore the parent's. */
	if (reason == NM_DEVICE_STATE_REASON_CARRIER)
		return;

	nm_device_set_unmanaged (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason);
}
예제 #14
0
static void
dispose (GObject *object)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (object);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);

	if (priv->disposed) {
		G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
		return;
	}
	priv->disposed = TRUE;

	nm_device_vlan_set_parent (self, NULL);

	G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
}
예제 #15
0
static void
set_property (GObject *object, guint prop_id,
			  const GValue *value, GParamSpec *pspec)
{
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);

	switch (prop_id) {
	case PROP_PARENT:
		nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), g_value_get_object (value));
		break;
	case PROP_VLAN_ID:
		priv->vlan_id = g_value_get_uint (value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
예제 #16
0
static void
constructed (GObject *object)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (object);
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
	int ifindex = nm_device_get_ifindex (NM_DEVICE (self));
	int parent_ifindex = -1, itype;
	int vlan_id;

	if (G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed)
		G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object);

	if (!priv->parent) {
		_LOGE (LOGD_VLAN, "no parent specified.");
		priv->invalid = TRUE;
		return;
	}

	itype = nm_platform_link_get_type (ifindex);
	if (itype != NM_LINK_TYPE_VLAN) {
		_LOGE (LOGD_VLAN, "failed to get VLAN interface type.");
		priv->invalid = TRUE;
		return;
	}

	if (!nm_platform_vlan_get_info (ifindex, &parent_ifindex, &vlan_id)) {
		_LOGW (LOGD_VLAN, "failed to get VLAN interface info.");
		priv->invalid = TRUE;
		return;
	}

	if (   parent_ifindex < 0
	    || parent_ifindex != nm_device_get_ip_ifindex (priv->parent)
	    || vlan_id < 0) {
		_LOGW (LOGD_VLAN, "VLAN parent ifindex (%d) or VLAN ID (%d) invalid.",
		       parent_ifindex, priv->vlan_id);
		priv->invalid = TRUE;
		return;
	}

	priv->vlan_id = vlan_id;
	_LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s",
	       priv->vlan_id, nm_device_get_iface (priv->parent));
}
예제 #17
0
static gboolean
realize (NMDevice *device,
         NMPlatformLink *plink,
         GError **error)
{
	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
	int parent_ifindex = -1, vlan_id = -1;
	NMDevice *parent;

	g_return_val_if_fail (plink, FALSE);

	g_assert (plink->type == NM_LINK_TYPE_VLAN);

	if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, &vlan_id)) {
		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
		             "(%s): failed to read VLAN properties", plink->name);
		return FALSE;
	}

	if (vlan_id < 0) {
		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
		             "(%s): VLAN ID invalid", plink->name);
		return FALSE;
	}

	if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) {
		parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
		if (!parent) {
			nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name);
			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
		                     "(%s): VLAN parent interface unknown", plink->name);
			return FALSE;
		}
	} else
		parent = NULL;

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

	return TRUE;
}
예제 #18
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;
}
예제 #19
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;
}
예제 #20
0
static void
parent_state_changed (NMDevice *parent,
                      NMDeviceState new_state,
                      NMDeviceState old_state,
                      NMDeviceStateReason reason,
                      gpointer user_data)
{
	NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);

	/* We'll react to our own carrier state notifications. Ignore the parent's. */
	if (reason == NM_DEVICE_STATE_REASON_CARRIER)
		return;

	if (new_state < NM_DEVICE_STATE_DISCONNECTED) {
		/* If the parent becomes unavailable or unmanaged so does the VLAN */
		nm_device_state_changed (NM_DEVICE (self), new_state, reason);
	} else if (   new_state == NM_DEVICE_STATE_DISCONNECTED
	           && old_state < NM_DEVICE_STATE_DISCONNECTED) {
		/* Mark VLAN interface as available/disconnected when the parent
		 * becomes available as a result of becoming initialized.
		 */
		nm_device_state_changed (NM_DEVICE (self), new_state, reason);
	}
}
예제 #21
0
static const char *
get_hw_address (NMDevice *device)
{
	return nm_device_vlan_get_hw_address (NM_DEVICE_VLAN (device));
}