static void
add_connections_for_aps (NmtConnectDevice *nmtdev,
                         const GPtrArray  *connections)
{
	NmtConnectConnection *nmtconn;
	NMConnection *conn;
	NMAccessPoint *ap;
	const GPtrArray *aps;
	GHashTable *seen_ssids;
	GBytes *ssid;
	char *ap_hash;
	int i, c;

	aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (nmtdev->device));
	if (!aps->len)
		return;

	seen_ssids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

	for (i = 0; i < aps->len; i++) {
		ap = aps->pdata[i];

		if (!nm_access_point_get_ssid (ap))
			continue;

		ap_hash = hash_ap (ap);
		if (g_hash_table_contains (seen_ssids, ap_hash)) {
			g_free (ap_hash);
			continue;
		}
		g_hash_table_add (seen_ssids, ap_hash);

		nmtconn = g_slice_new0 (NmtConnectConnection);
		nmtconn->device = nmtdev->device;
		nmtconn->ap = g_object_ref (ap);
		ssid = nm_access_point_get_ssid (ap);
		if (ssid)
			nmtconn->ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
			                                       g_bytes_get_size (ssid));

		for (c = 0; c < connections->len; c++) {
			conn = connections->pdata[c];
			if (   nm_device_connection_valid (nmtdev->device, conn)
			    && nm_access_point_connection_valid (ap, conn)) {
				nmtconn->name = nm_connection_get_id (conn);
				nmtconn->conn = g_object_ref (conn);
				break;
			}
		}

		if (!nmtconn->name)
			nmtconn->name = nmtconn->ssid ? nmtconn->ssid : "<unknown>";

		nmtdev->conns = g_slist_prepend (nmtdev->conns, nmtconn);
	}

	g_hash_table_unref (seen_ssids);
}
static void
add_connections_for_aps (NmtConnectDevice *nmtdev,
                         GSList           *connections)
{
	NmtConnectConnection *nmtconn;
	NMConnection *conn;
	NMAccessPoint *ap;
	const GPtrArray *aps;
	GHashTable *seen_ssids;
	char *ap_hash;
	GSList *iter;
	int i;

	aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (nmtdev->device));
	if (!aps)
		return;

	seen_ssids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

	for (i = 0; i < aps->len; i++) {
		ap = aps->pdata[i];

		if (!nm_access_point_get_ssid (ap))
			continue;

		ap_hash = hash_ap (ap);
		if (g_hash_table_contains (seen_ssids, ap_hash)) {
			g_free (ap_hash);
			continue;
		}
		g_hash_table_add (seen_ssids, ap_hash);

		nmtconn = g_slice_new0 (NmtConnectConnection);
		nmtconn->device = nmtdev->device;
		nmtconn->ap = g_object_ref (ap);
		nmtconn->ssid = nm_utils_ssid_to_utf8 (nm_access_point_get_ssid (ap));

		for (iter = connections; iter; iter = iter->next) {
			conn = iter->data;
			if (   nm_device_connection_valid (nmtdev->device, conn)
			    && nm_access_point_connection_valid (ap, conn)) {
				nmtconn->name = nm_connection_get_id (conn);
				nmtconn->conn = g_object_ref (conn);
				break;
			}
		}

		if (!iter)
			nmtconn->name = nmtconn->ssid;

		nmtdev->conns = g_slist_prepend (nmtdev->conns, nmtconn);
	}

	g_hash_table_unref (seen_ssids);
}
static void
add_connections_for_device (NmtConnectDevice *nmtdev,
                            const GPtrArray  *connections)
{
	int i;

	for (i = 0; i < connections->len; i++) {
		NMConnection *conn = connections->pdata[i];
		NMSettingConnection *s_con;

		s_con = nm_connection_get_setting_connection (conn);
		if (nm_setting_connection_get_master (s_con))
			continue;

		if (nm_device_connection_valid (nmtdev->device, conn)) {
			NmtConnectConnection *nmtconn = g_slice_new0 (NmtConnectConnection);

			nmtconn->name = nm_connection_get_id (conn);
			nmtconn->device = nmtdev->device;
			nmtconn->conn = g_object_ref (conn);
			nmtdev->conns = g_slist_prepend (nmtdev->conns, nmtconn);
		}
	}
}
static void
add_connections_for_device (NmtConnectDevice *nmtdev,
                            GSList           *connections)
{
	GSList *iter;

	for (iter = connections; iter; iter = iter->next) {
		NMConnection *conn = iter->data;
		NMSettingConnection *s_con;

		s_con = nm_connection_get_setting_connection (conn);
		if (nm_setting_connection_get_master (s_con))
			continue;

		if (nm_device_connection_valid (nmtdev->device, conn)) {
			NmtConnectConnection *nmtconn = g_slice_new0 (NmtConnectConnection);

			nmtconn->name = nm_connection_get_id (conn);
			nmtconn->device = nmtdev->device;
			nmtconn->conn = g_object_ref (conn);
			nmtdev->conns = g_slist_prepend (nmtdev->conns, nmtconn);
		}
	}
}
static void
build_vlan_parent_list (CEPageVlan *self, GSList *devices)
{
    CEPageVlanPrivate *priv = CE_PAGE_VLAN_GET_PRIVATE (self);
    GSList *connections, *c_iter, *d_iter;
    GPtrArray *parents;
    VlanParent *parent;
    NMDevice *device;
    const char *iface, *mac, *id;
    int i;

    parents = g_ptr_array_new ();

    /* Devices with no L2 configuration can spawn VLANs directly. At the
     * moment, this means just Ethernet.
     */
    for (d_iter = devices; d_iter; d_iter = d_iter->next) {
        device = d_iter->data;

        if (!NM_IS_DEVICE_ETHERNET (device))
            continue;

        parent = g_slice_new (VlanParent);
        parent->device = device;
        parent->connection = NULL;

        iface = nm_device_get_iface (device);
        mac = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
        parent->label = g_strdup_printf ("%s (%s)", iface, mac);

        g_ptr_array_add (parents, parent);
    }

    /* Otherwise, VLANs have to be built on top of configured connections */
    connections = nm_remote_settings_list_connections (CE_PAGE (self)->settings);
    for (c_iter = connections; c_iter; c_iter = c_iter->next) {
        NMConnection *candidate = c_iter->data;
        NMSettingConnection *s_con = nm_connection_get_setting_connection (candidate);

        if (nm_setting_connection_get_master (s_con))
            continue;

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

            if (nm_device_connection_valid (device, candidate)) {
                parent = g_slice_new (VlanParent);
                parent->device = device;
                parent->connection = candidate;

                iface = nm_device_get_iface (device);
                id = nm_setting_connection_get_id (s_con);

                parent->label = g_strdup_printf ("%s (%s)", iface, id);
                g_ptr_array_add (parents, parent);
                /* no break here; the connection may apply to multiple devices */
            }
        }
    }

    g_slist_free (connections);

    g_ptr_array_sort (parents, sort_parents);
    g_ptr_array_add (parents, NULL);

    priv->parent_labels = g_new (char *, parents->len);
    priv->parents = (VlanParent **)g_ptr_array_free (parents, FALSE);

    for (i = 0; priv->parents[i]; i++)
        priv->parent_labels[i] = priv->parents[i]->label;
    priv->parent_labels[i] = NULL;
}