NMDevice *
nm_device_factory_create_device (NMDeviceFactory *factory,
                                 const char *iface,
                                 const NMPlatformLink *plink,
                                 NMConnection *connection,
                                 gboolean *out_ignore,
                                 GError **error)
{
	NMDeviceFactoryInterface *interface;
	const NMLinkType *link_types = NULL;
	const char **setting_types = NULL;
	int i;

	g_return_val_if_fail (factory, NULL);
	g_return_val_if_fail (iface && *iface, NULL);
	g_return_val_if_fail (plink || connection, NULL);
	g_return_val_if_fail (!plink || !connection, NULL);

	nm_device_factory_get_supported_types (factory, &link_types, &setting_types);

	if (plink) {
		g_return_val_if_fail (strcmp (iface, plink->name) == 0, NULL);

		for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
			if (plink->type == link_types[i])
				break;
		}

		if (link_types[i] == NM_LINK_TYPE_UNKNOWN) {
			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
			             "Device factory %s does not support link type %s (%d)",
			             G_OBJECT_TYPE_NAME (factory),
			             plink->kind, plink->type);
			return NULL;
		}
	} else if (connection) {
		for (i = 0; setting_types && setting_types[i]; i++) {
			if (nm_connection_is_type (connection, setting_types[i]))
				break;
		}

		if (!setting_types[i]) {
			g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
			             "Device factory %s does not support connection type %s",
			             G_OBJECT_TYPE_NAME (factory),
			             nm_connection_get_connection_type (connection));
			return NULL;
		}
	}

	interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
	if (!interface->create_device) {
		g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
		             "Device factory %s cannot manage new devices",
		             G_OBJECT_TYPE_NAME (factory));
		return NULL;
	}

	return interface->create_device (factory, iface, plink, connection, out_ignore);
}
NMDeviceFactory *
nm_device_factory_manager_find_factory_for_connection (NMConnection *connection)
{
	const char *stypes[2] = { nm_connection_get_connection_type (connection), NULL };

	g_assert (stypes[0]);
	return find_factory (NULL, stypes);
}
char *
nm_device_factory_get_connection_iface (NMDeviceFactory *factory,
                                        NMConnection *connection,
                                        const char *parent_iface,
                                        GError **error)
{
	NMDeviceFactoryInterface *klass;
	char *ifname;

	g_return_val_if_fail (factory != NULL, NULL);
	g_return_val_if_fail (connection != NULL, NULL);
	g_return_val_if_fail (!error || !*error, NULL);

	klass = NM_DEVICE_FACTORY_GET_INTERFACE (factory);

	if (klass->get_connection_iface)
		ifname = klass->get_connection_iface (factory, connection, parent_iface);
	else
		ifname = g_strdup (nm_connection_get_interface_name (connection));

	if (!ifname) {
		g_set_error (error,
		             NM_MANAGER_ERROR,
		             NM_MANAGER_ERROR_FAILED,
		             "failed to determine interface name: error determine name for %s",
		             nm_connection_get_connection_type (connection));
		return NULL;
	}

	if (!nm_utils_iface_valid_name (ifname)) {
		g_set_error (error,
		             NM_MANAGER_ERROR,
		             NM_MANAGER_ERROR_FAILED,
		             "failed to determine interface name: name \"%s\" is invalid",
		             ifname);
		g_free (ifname);
		return NULL;
	}

	return ifname;
}
static void
get_property (GObject *object, guint prop_id,
              GValue *value, GParamSpec *pspec)
{
	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
	GPtrArray *devices;
	NMDevice *master_device = NULL;

	switch (prop_id) {
	case PROP_CONNECTION:
		g_value_set_string (value, nm_connection_get_path (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_ID:
		g_value_set_string (value, nm_connection_get_id (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_UUID:
		g_value_set_string (value, nm_connection_get_uuid (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_TYPE:
		g_value_set_string (value, nm_connection_get_connection_type (NM_CONNECTION (priv->settings_connection)));
		break;
	case PROP_SPECIFIC_OBJECT:
		g_value_set_string (value, priv->specific_object ? priv->specific_object : "/");
		break;
	case PROP_DEVICES:
		devices = g_ptr_array_sized_new (2);
		if (priv->device && priv->state < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
			g_ptr_array_add (devices, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->device))));
		g_ptr_array_add (devices, NULL);
		g_value_take_boxed (value, (char **) g_ptr_array_free (devices, FALSE));
		break;
	case PROP_STATE:
		if (priv->state_set)
			g_value_set_uint (value, priv->state);
		else {
			/* When the AC has just been created, its externally-visible state should
			 * be "ACTIVATING", even though internally it is "UNKNOWN".
			 */
			g_value_set_uint (value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING);
		}
		break;
	case PROP_DEFAULT:
		g_value_set_boolean (value, priv->is_default);
		break;
	case PROP_IP4_CONFIG:
		/* The IP and DHCP config properties may be overridden by a subclass */
		g_value_set_string (value, "/");
		break;
	case PROP_DHCP4_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_DEFAULT6:
		g_value_set_boolean (value, priv->is_default6);
		break;
	case PROP_IP6_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_DHCP6_CONFIG:
		g_value_set_string (value, "/");
		break;
	case PROP_VPN:
		g_value_set_boolean (value, priv->vpn);
		break;
	case PROP_MASTER:
		if (priv->master)
			master_device = nm_active_connection_get_device (priv->master);
		nm_utils_g_value_set_object_path (value, master_device);
		break;
	case PROP_INT_SUBJECT:
		g_value_set_object (value, priv->subject);
		break;
	case PROP_INT_MASTER_READY:
		g_value_set_boolean (value, priv->master_ready);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}