static void
recheck_services_enabled (NmaBtDevice *self)
{
	NmaBtDevicePrivate *priv = NMA_BT_DEVICE_GET_PRIVATE (self);
	GSList *list, *iter;
	gboolean pan = FALSE, dun = FALSE;

	/* Retrieve initial enabled state for both PAN and DUN; if there are any
	 * existing Bluetooth connections for the given device for either PAN
	 * or DUN, then we consider that service enabled.
	 */
	list = nm_remote_settings_list_connections (priv->settings);
	for (iter = list; iter != NULL; iter = g_slist_next (iter)) {
		NMConnection *connection = iter->data;

		if (match_connection_bdaddr (connection, priv->bdaddr_array)) {
			NMSettingBluetooth *s_bt;
			const char *type;

			s_bt = nm_connection_get_setting_bluetooth (connection);
			g_assert (s_bt);
			type = nm_setting_bluetooth_get_connection_type (s_bt);
			if (priv->has_pan && g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) == 0)
				pan = TRUE;
			else if (priv->has_dun && g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_DUN) == 0)
				dun =  TRUE;
		}
	}
	g_slist_free (list);

	_set_pan_enabled (self, pan);
	_set_dun_enabled (self, dun);
}
static gboolean
hwaddr_matches (NMDevice *device,
                NMConnection *connection,
                const guint8 *other_hwaddr,
                guint other_hwaddr_len,
                gboolean fail_if_no_hwaddr)
{
    NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
    NMSettingBluetooth *s_bt;
    const GByteArray *mac = NULL;
    gboolean matches = FALSE;
    GByteArray *devmac;

    s_bt = nm_connection_get_setting_bluetooth (connection);
    if (s_bt)
        mac = nm_setting_bluetooth_get_bdaddr (s_bt);

    if (mac) {
        devmac = nm_utils_hwaddr_atoba (priv->bdaddr, ARPHRD_ETHER);
        g_return_val_if_fail (devmac != NULL, FALSE);
        g_return_val_if_fail (devmac->len == mac->len, FALSE);

        if (other_hwaddr) {
            g_return_val_if_fail (other_hwaddr_len == devmac->len, FALSE);
            matches = (memcmp (mac->data, other_hwaddr, mac->len) == 0) ? TRUE : FALSE;
        } else
            matches = (memcmp (mac->data, devmac->data, mac->len) == 0) ? TRUE : FALSE;

        g_byte_array_free (devmac, TRUE);
        return matches;
    } else if (fail_if_no_hwaddr == FALSE)
        return TRUE;

    return FALSE;
}
Esempio n. 3
0
static void
remove_connections_read (NMRemoteSettings *settings, gpointer user_data)
{
	RemoveInfo *info = user_data;
	GSList *list, *iter;

	g_source_remove (info->timeout_id);

	g_message ("Removing Bluetooth connections for %s", info->str_bdaddr);

	list = nm_remote_settings_list_connections (settings);
	for (iter = list; iter != NULL; iter = g_slist_next (iter)) {
		NMConnection *connection = iter->data;
		NMSettingBluetooth *s_bt;
		const GByteArray *tmp;

		s_bt = nm_connection_get_setting_bluetooth (connection);
		if (s_bt) {
			tmp = nm_setting_bluetooth_get_bdaddr (s_bt);
			if (tmp && memcmp (tmp->data, info->bdaddr->data, tmp->len) == 0)
				nm_remote_connection_delete (NM_REMOTE_CONNECTION (connection), delete_cb, NULL);
		}
	}
	g_slist_free (list);

	remove_cleanup (info);
}
Esempio n. 4
0
static gboolean
connection_compatible (NMBluezDevice *self, NMConnection *connection)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
	NMSettingBluetooth *s_bt;
	const char *bt_type;
	const char *bdaddr;

	if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME))
		return FALSE;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (!s_bt)
		return FALSE;

	if (!priv->address)
		return FALSE;

	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
	if (!bdaddr)
		return FALSE;
	if (!nm_utils_hwaddr_matches (bdaddr, -1, priv->address, -1))
		return FALSE;

	bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
	if (   g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)
	    && !(priv->capabilities & NM_BT_CAPABILITY_DUN))
		return FALSE;

	if (   g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)
	    && !(priv->capabilities & NM_BT_CAPABILITY_NAP))
		return FALSE;

	return TRUE;
}
Esempio n. 5
0
static gboolean
connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
	NMSettingConnection *s_con;
	NMSettingBluetooth *s_bt;
	const char *ctype;
	const GByteArray *mac;
	const char *hw_str;
	struct ether_addr *hw_mac;
	NMBluetoothCapabilities dev_caps;
	NMBluetoothCapabilities bt_type;

	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	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_BLUETOOTH_SETTING_NAME) != 0) {
		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_NOT_BT_CONNECTION,
		             "The connection was not a Bluetooth connection.");
		return FALSE;
	}

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (!s_bt) {
		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_BT_CONNECTION,
		             "The connection was not a valid Bluetooth connection.");
		return FALSE;
	}

	/* Check BT address */
	hw_str = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
	if (hw_str) {
		hw_mac = ether_aton (hw_str);
		if (!hw_mac) {
			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_INVALID_DEVICE_MAC,
			             "Invalid device MAC address.");
			return FALSE;
		}
		mac = nm_setting_bluetooth_get_bdaddr (s_bt);
		if (mac && hw_mac && memcmp (mac->data, hw_mac->ether_addr_octet, ETH_ALEN)) {
			g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MAC_MISMATCH,
			             "The MACs of the device and the connection didn't match.");
			return FALSE;
		}
	}

	dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device));
	bt_type = get_connection_bt_type (connection);
	if (!(bt_type & dev_caps)) {
		g_set_error (error, NM_DEVICE_BT_ERROR, NM_DEVICE_BT_ERROR_MISSING_DEVICE_CAPS,
		             "The device missed BT capabilities required by the connection.");
		return FALSE;
	}

	return TRUE;
}
static gboolean
check_connection_compatible (NMDevice *device,
                             NMConnection *connection,
                             GError **error)
{
    NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
    NMSettingConnection *s_con;
    NMSettingBluetooth *s_bt;
    const GByteArray *array;
    char *str;
    int addr_match = FALSE;
    guint32 bt_type;

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

    if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME)) {
        g_set_error (error,
                     NM_BT_ERROR, NM_BT_ERROR_CONNECTION_NOT_BT,
                     "The connection was not a Bluetooth connection.");
        return FALSE;
    }

    s_bt = nm_connection_get_setting_bluetooth (connection);
    if (!s_bt) {
        g_set_error (error,
                     NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INVALID,
                     "The connection was not a valid Bluetooth connection.");
        return FALSE;
    }

    array = nm_setting_bluetooth_get_bdaddr (s_bt);
    if (!array || (array->len != ETH_ALEN)) {
        g_set_error (error,
                     NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INVALID,
                     "The connection did not contain a valid Bluetooth address.");
        return FALSE;
    }

    bt_type = get_connection_bt_type (connection);
    if (!(bt_type & priv->capabilities)) {
        g_set_error (error,
                     NM_BT_ERROR, NM_BT_ERROR_CONNECTION_INCOMPATIBLE,
                     "The connection was not compatible with the device's capabilities.");
        return FALSE;
    }

    str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
                           array->data[0], array->data[1], array->data[2],
                           array->data[3], array->data[4], array->data[5]);
    addr_match = !strcmp (priv->bdaddr, str);
    g_free (str);

    return addr_match;
}
static gboolean
match_connection_bdaddr (NMConnection *connection, const GByteArray *bdaddr)
{
	NMSettingBluetooth *s_bt;
	const GByteArray *tmp;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (s_bt) {
		tmp = nm_setting_bluetooth_get_bdaddr (s_bt);
		if (tmp && memcmp (tmp->data, bdaddr->data, tmp->len) == 0)
			return TRUE;
	}
	return FALSE;
}
Esempio n. 8
0
static gboolean
connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
	NMSettingBluetooth *s_bt;
	const char *hw_addr, *setting_addr;
	NMBluetoothCapabilities dev_caps;
	NMBluetoothCapabilities bt_type;

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

	if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
		g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
		             _("The connection was not a Bluetooth connection."));
		return FALSE;
	}

	/* Check BT address */
	hw_addr = nm_device_bt_get_hw_address (NM_DEVICE_BT (device));
	if (hw_addr) {
		if (!nm_utils_hwaddr_valid (hw_addr, ETH_ALEN)) {
			g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
			                     _("Invalid device Bluetooth address."));
			return FALSE;
		}
		s_bt = nm_connection_get_setting_bluetooth (connection);
		setting_addr = nm_setting_bluetooth_get_bdaddr (s_bt);
		if (setting_addr && !nm_utils_hwaddr_matches (setting_addr, -1, hw_addr, -1)) {
			g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
			                     _("The Bluetooth addresses of the device and the connection didn't match."));
			return FALSE;
		}
	}

	dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device));
	bt_type = get_connection_bt_type (connection);
	if (!(bt_type & dev_caps)) {
		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
		                     _("The device is lacking Bluetooth capabilities required by the connection."));
		return FALSE;
	}

	return TRUE;
}
Esempio n. 9
0
static NMBluetoothCapabilities
get_connection_bt_type (NMConnection *connection)
{
	NMSettingBluetooth *s_bt;
	const char *bt_type;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (!s_bt)
		return NM_BT_CAPABILITY_NONE;

	bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
	g_assert (bt_type);

	if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN))
		return NM_BT_CAPABILITY_DUN;
	else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU))
		return NM_BT_CAPABILITY_NAP;

	return NM_BT_CAPABILITY_NONE;
}
CEPage *
ce_page_bluetooth_new (NMConnectionEditor *editor,
                       NMConnection *connection,
                       GtkWindow *parent_window,
                       NMClient *client,
                       const char **out_secrets_setting_name,
                       GError **error)
{
	CEPageBluetooth *self;
	CEPageBluetoothPrivate *priv;

	self = CE_PAGE_BLUETOOTH (ce_page_new (CE_TYPE_PAGE_BLUETOOTH,
	                          editor,
	                          connection,
	                          parent_window,
	                          client,
	                          UIDIR "/ce-page-bluetooth.ui",
	                          "BluetoothPage",
	                          _("Bluetooth")));
	if (!self) {
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load Bluetooth user interface."));
		return NULL;
	}

	bluetooth_private_init (self);
	priv = CE_PAGE_BLUETOOTH_GET_PRIVATE (self);

	priv->setting = nm_connection_get_setting_bluetooth (connection);
	if (!priv->setting) {
		priv->setting = NM_SETTING_BLUETOOTH (nm_setting_bluetooth_new ());
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
	}

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

	*out_secrets_setting_name = NM_SETTING_BLUETOOTH_SETTING_NAME;

	return CE_PAGE (self);
}
static gboolean
match_connection_service (NMConnection *connection,
                          const GByteArray *bdaddr,
                          gboolean pan)
{
	NMSettingBluetooth *s_bt;
	const char *type;

	if (!match_connection_bdaddr (connection, bdaddr))
		return FALSE;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	g_assert (s_bt);
	type = nm_setting_bluetooth_get_connection_type (s_bt);
	if (pan) {
		if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) != 0)
			return FALSE;
	} else {
		if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_DUN) != 0)
			return FALSE;
	}

	return TRUE;
}
static gboolean
nm_connection_editor_set_connection (NMConnectionEditor *editor,
                                     NMConnection *orig_connection,
                                     GError **error)
{
	NMSettingConnection *s_con;
	const char *connection_type;
	const char *slave_type;
	gboolean success = FALSE;
	GSList *iter, *copy;

	g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (orig_connection), FALSE);

	/* clean previous connection */
	if (editor->connection)
		g_object_unref (editor->connection);

	editor->connection = nm_simple_connection_new_clone (orig_connection);

	editor->orig_connection = g_object_ref (orig_connection);
	nm_connection_editor_update_title (editor);

	/* Handle CA cert ignore stuff */
	eap_method_ca_cert_ignore_load (editor->connection);

	s_con = nm_connection_get_setting_connection (editor->connection);
	g_assert (s_con);

	connection_type = nm_setting_connection_get_connection_type (s_con);
	if (!add_page (editor, ce_page_general_new, editor->connection, error))
		goto out;
	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_8021x_security_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_dcb_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
		if (!add_page (editor, ce_page_wifi_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_wifi_security_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vpn_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ip_tunnel_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_dsl_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
	           !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
		if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
		NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (editor->connection);
		const char *type = nm_setting_bluetooth_get_connection_type (s_bt);
		g_assert (type);

		if (!add_page (editor, ce_page_bluetooth_new, editor->connection, error))
			goto out;
		if (!g_strcmp0 (type, "dun")) {
			if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
				goto out;
			if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
				goto out;
		}
	} else if (!strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_infiniband_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bond_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VLAN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vlan_new, editor->connection, error))
			goto out;
	} else {
		g_warning ("Unhandled setting type '%s'", connection_type);
	}

	slave_type = nm_setting_connection_get_slave_type (s_con);
	if (!g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_port_new, editor->connection, error))
			goto out;
	} else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_port_new, editor->connection, error))
			goto out;
	}

	if (   nm_connection_get_setting_ip4_config (editor->connection)
	    && !add_page (editor, ce_page_ip4_new, editor->connection, error))
		goto out;
	if (   nm_connection_get_setting_ip6_config (editor->connection)
	    && !add_page (editor, ce_page_ip6_new, editor->connection, error))
		goto out;

	/* After all pages are created, then kick off secrets requests that any
	 * the pages may need to make; if they don't need any secrets, then let
	 * them finish initialization.  The list might get modified during the loop
	 * which is why copy the list here.
	 */
	copy = g_slist_copy (editor->initializing_pages);
	for (iter = copy; iter; iter = g_slist_next (iter)) {
		CEPage *page = CE_PAGE (iter->data);
		const char *setting_name = g_object_get_data (G_OBJECT (page), SECRETS_TAG);

		if (!setting_name) {
			/* page doesn't need any secrets */
			ce_page_complete_init (page, NULL, NULL, NULL);
		} else if (!NM_IS_REMOTE_CONNECTION (editor->orig_connection)) {
			/* We want to get secrets using ->orig_connection, since that's the
			 * remote connection which can actually respond to secrets requests.
			 * ->connection is a plain NMConnection copy of ->orig_connection
			 * which is what gets changed when users modify anything.  But when
			 * creating or importing, ->orig_connection will be an NMConnection
			 * since the new connection hasn't been added to NetworkManager yet.
			 * So basically, skip requesting secrets if the connection can't
			 * handle a secrets request.
			 */
			ce_page_complete_init (page, setting_name, NULL, NULL);
		} else {
			/* Page wants secrets, get them */
			get_secrets_for_page (editor, page, setting_name);
		}
		g_object_set_data (G_OBJECT (page), SECRETS_TAG, NULL);
	}
	g_slist_free (copy);

	/* set the UI */
	recheck_initialization (editor);
	success = TRUE;

out:
	return success;
}
static gboolean
complete_connection (NMDevice *device,
                     NMConnection *connection,
                     const char *specific_object,
                     const GSList *existing_connections,
                     GError **error)
{
    NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
    NMSettingBluetooth *s_bt;
    const GByteArray *setting_bdaddr;
    struct ether_addr *devaddr = ether_aton (priv->bdaddr);
    const char *ctype;
    gboolean is_dun = FALSE, is_pan = FALSE;
    NMSettingGsm *s_gsm;
    NMSettingCdma *s_cdma;
    NMSettingSerial *s_serial;
    NMSettingPPP *s_ppp;
    const char *format = NULL, *preferred = NULL;

    s_gsm = nm_connection_get_setting_gsm (connection);
    s_cdma = nm_connection_get_setting_cdma (connection);
    s_serial = nm_connection_get_setting_serial (connection);
    s_ppp = nm_connection_get_setting_ppp (connection);

    s_bt = nm_connection_get_setting_bluetooth (connection);
    if (!s_bt) {
        s_bt = (NMSettingBluetooth *) nm_setting_bluetooth_new ();
        nm_connection_add_setting (connection, NM_SETTING (s_bt));
    }

    ctype = nm_setting_bluetooth_get_connection_type (s_bt);
    if (ctype) {
        if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_DUN))
            is_dun = TRUE;
        else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_PANU))
            is_pan = TRUE;
    } else {
        if (s_gsm || s_cdma)
            is_dun = TRUE;
        else if (priv->capabilities & NM_BT_CAPABILITY_NAP)
            is_pan = TRUE;
    }

    if (is_pan) {
        /* Make sure the device supports PAN */
        if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "PAN required but Bluetooth device does not support NAP");
            return FALSE;
        }

        /* PAN can't use any DUN-related settings */
        if (s_gsm || s_cdma || s_serial || s_ppp) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "PAN incompatible with GSM, CDMA, or serial settings");
            return FALSE;
        }

        g_object_set (G_OBJECT (s_bt),
                      NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
                      NULL);

        format = _("PAN connection %d");
    } else if (is_dun) {
        /* Make sure the device supports PAN */
        if (!(priv->capabilities & NM_BT_CAPABILITY_DUN)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "DUN required but Bluetooth device does not support DUN");
            return FALSE;
        }

        /* Need at least a GSM or a CDMA setting */
        if (!s_gsm && !s_cdma) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "Setting requires DUN but no GSM or CDMA setting is present");
            return FALSE;
        }

        g_object_set (G_OBJECT (s_bt),
                      NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN,
                      NULL);

        if (s_gsm) {
            format = _("GSM connection %d");
            if (!nm_setting_gsm_get_number (s_gsm))
                g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL);
        } else if (s_cdma) {
            format = _("CDMA connection %d");
            if (!nm_setting_cdma_get_number (s_cdma))
                g_object_set (G_OBJECT (s_cdma), NM_SETTING_GSM_NUMBER, "#777", NULL);
        } else
            format = _("DUN connection %d");
    } else {
        g_set_error_literal (error,
                             NM_SETTING_BLUETOOTH_ERROR,
                             NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                             "Unknown/unhandled Bluetooth connection type");
        return FALSE;
    }

    nm_utils_complete_generic (connection,
                               NM_SETTING_BLUETOOTH_SETTING_NAME,
                               existing_connections,
                               format,
                               preferred,
                               is_dun ? FALSE : TRUE); /* No IPv6 yet for DUN */

    setting_bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
    if (setting_bdaddr) {
        /* Make sure the setting BT Address (if any) matches the device's */
        if (memcmp (setting_bdaddr->data, devaddr->ether_addr_octet, ETH_ALEN)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 NM_SETTING_BLUETOOTH_BDADDR);
            return FALSE;
        }
    } else {
        GByteArray *bdaddr;
        const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };

        /* Lock the connection to this device by default */
        if (memcmp (devaddr->ether_addr_octet, null_mac, ETH_ALEN)) {
            bdaddr = g_byte_array_sized_new (ETH_ALEN);
            g_byte_array_append (bdaddr, devaddr->ether_addr_octet, ETH_ALEN);
            g_object_set (G_OBJECT (s_bt), NM_SETTING_BLUETOOTH_BDADDR, bdaddr, NULL);
            g_byte_array_free (bdaddr, TRUE);
        }
    }

    return TRUE;
}
static void
new_connection_mobile_wizard_done (NMAMobileWizard *wizard,
                                   gboolean canceled,
                                   NMAMobileWizardAccessMethod *method,
                                   gpointer user_data)
{
	WizardInfo *info = user_data;
	NMConnection *connection = NULL;
	char *detail = NULL;
	NMSetting *type_setting = NULL;

	if (canceled)
		goto out;

	if (method) {
		switch (method->devtype) {
		case NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS:
			type_setting = nm_setting_gsm_new ();
			/* De-facto standard for GSM */
			g_object_set (type_setting,
			              NM_SETTING_GSM_NUMBER, "*99#",
			              NM_SETTING_GSM_USERNAME, method->username,
			              NM_SETTING_GSM_PASSWORD, method->password,
			              NM_SETTING_GSM_APN, method->gsm_apn,
			              NULL);
			break;
		case NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO:
			type_setting = nm_setting_cdma_new ();
			/* De-facto standard for CDMA */
			g_object_set (type_setting,
			              NM_SETTING_CDMA_NUMBER, "#777",
			              NM_SETTING_GSM_USERNAME, method->username,
			              NM_SETTING_GSM_PASSWORD, method->password,
			              NULL);
			break;
		default:
			g_assert_not_reached ();
			break;
		}

		if (method->plan_name)
			detail = g_strdup_printf ("%s %s %%d", method->provider_name, method->plan_name);
		else
			detail = g_strdup_printf ("%s connection %%d", method->provider_name);
	}

	if (!detail)
		detail = g_strdup (_("Bluetooth connection %d"));
	connection = ce_page_new_connection (detail,
	                                     NM_SETTING_BLUETOOTH_SETTING_NAME,
	                                     FALSE,
	                                     info->client,
	                                     user_data);
	g_free (detail);
	nm_connection_add_setting (connection, nm_setting_bluetooth_new ());
	g_object_set (nm_connection_get_setting_bluetooth (connection),
	              NM_SETTING_BLUETOOTH_TYPE, info->type, NULL);

	if (type_setting) {
		nm_connection_add_setting (connection, type_setting);
		nm_connection_add_setting (connection, nm_setting_ppp_new ());
	}

out:
	(*info->result_func) (connection, canceled, NULL, info->user_data);

	if (wizard)
		nma_mobile_wizard_destroy (wizard);

	g_object_unref (info->client);
	g_free (info);
}