bearer-qmi: implement connection logic using existing profiles

This commit is contained in:
Aleksander Morgado
2021-04-08 11:58:52 +02:00
parent ce383abfe1
commit 0d60b9497b

View File

@@ -415,6 +415,7 @@ static void cleanup_event_report_unsolicited_events (MMBearerQmi *self,
typedef enum {
CONNECT_STEP_FIRST,
CONNECT_STEP_LOAD_PROFILE_SETTINGS,
CONNECT_STEP_OPEN_QMI_PORT,
CONNECT_STEP_SETUP_DATA_FORMAT,
CONNECT_STEP_SETUP_LINK,
@@ -445,6 +446,7 @@ typedef struct {
MMPortQmi *qmi;
QmiSioPort sio_port;
gint profile_id;
MMBearerIpMethod ip_method;
gboolean explicit_qmi_open;
gchar *user;
@@ -980,32 +982,30 @@ static QmiMessageWdsStartNetworkInput *
build_start_network_input (ConnectContext *ctx)
{
QmiMessageWdsStartNetworkInput *input;
gboolean has_user, has_password;
g_assert (ctx->running_ipv4 || ctx->running_ipv6);
g_assert (!(ctx->running_ipv4 && ctx->running_ipv6));
input = qmi_message_wds_start_network_input_new ();
if (ctx->apn && ctx->apn[0])
qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL);
/* When requesting to connect through a profile, add the profile-id setting */
if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
g_assert (ctx->profile_id <= (gint)G_MAXUINT8);
qmi_message_wds_start_network_input_set_profile_index_3gpp (input, (guint8)ctx->profile_id, NULL);
} else {
/* If user gives empty string as APN, we also skip setting it in the
* request. */
if (ctx->apn && ctx->apn[0])
qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL);
has_user = (ctx->user && ctx->user[0]);
has_password = (ctx->password && ctx->password[0]);
/* Need to add auth info? */
if (has_user || has_password || ctx->auth != QMI_WDS_AUTHENTICATION_NONE) {
/* We define a valid auth preference if we have either user or password, or an explicit
* request for one to be set. If no explicit one was given, default to CHAP. */
qmi_message_wds_start_network_input_set_authentication_preference (
input,
(ctx->auth != QMI_WDS_AUTHENTICATION_NONE) ? ctx->auth : QMI_WDS_AUTHENTICATION_CHAP,
NULL);
if (has_user)
qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL);
if (has_password)
qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL);
/* Auth info */
qmi_message_wds_start_network_input_set_authentication_preference (input, ctx->auth, NULL);
if (ctx->auth != QMI_WDS_AUTHENTICATION_NONE) {
if (ctx->user)
qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL);
if (ctx->user)
qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL);
}
}
/* Only add the IP family preference TLV if explicitly requested a given
@@ -1486,6 +1486,66 @@ qmi_port_open_ready (MMPortQmi *qmi,
connect_context_step (task);
}
static gboolean
load_ip_type_settings_from_profile (ConnectContext *ctx,
MM3gppProfile *profile,
GError **error)
{
MMBearerIpFamily ip_family;
ip_family = mm_3gpp_profile_get_ip_type (profile);
if (mm_3gpp_normalize_ip_family (&ip_family))
ctx->no_ip_family_preference = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV4)
ctx->ipv4 = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV6)
ctx->ipv6 = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV4V6) {
ctx->ipv4 = TRUE;
ctx->ipv6 = TRUE;
}
if (!ctx->ipv4 && !ctx->ipv6) {
g_autofree gchar *str = NULL;
str = mm_bearer_ip_family_build_string_from_mask (ip_family);
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported IP type requested: '%s'", str);
return FALSE;
}
return TRUE;
}
static void
get_profile_ready (MMIfaceModem3gppProfileManager *modem,
GAsyncResult *res,
GTask *task)
{
ConnectContext *ctx;
GError *error = NULL;
g_autoptr(MM3gppProfile) profile = NULL;
ctx = g_task_get_task_data (task);
profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (modem, res, &error);
if (!profile) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (!load_ip_type_settings_from_profile (ctx, profile, &error)) {
g_prefix_error (&error, "Couldn't load ip type settings from profile: ");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
/* Keep on */
ctx->step++;
connect_context_step (task);
}
static void
connect_context_step (GTask *task)
{
@@ -1518,11 +1578,24 @@ connect_context_step (GTask *task)
switch (ctx->step) {
case CONNECT_STEP_FIRST:
g_assert (ctx->ipv4 || ctx->ipv6);
ctx->step++;
/* fall through */
case CONNECT_STEP_LOAD_PROFILE_SETTINGS:
if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
mm_obj_dbg (self, "loading connection settings from profile '%d'...", ctx->profile_id);
mm_iface_modem_3gpp_profile_manager_get_profile (
MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (ctx->modem),
ctx->profile_id,
(GAsyncReadyCallback)get_profile_ready,
task);
return;
}
ctx->step++;
/* fall through */
case CONNECT_STEP_OPEN_QMI_PORT:
g_assert (ctx->ipv4 || ctx->ipv6);
/* If we're explicitly opening the port (e.g. using a different cdc-wdm
* port because the primary one is already connected by a different
* bearer), then make sure we also close it if anything goes wrong and
@@ -1945,6 +2018,9 @@ connect_context_step (GTask *task)
ctx->ipv6_config);
mm_bearer_connect_result_set_multiplexed (connect_result, !!ctx->link);
if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)
mm_bearer_connect_result_set_profile_id (connect_result, ctx->profile_id);
complete_connect (task, connect_result, NULL);
return;
}
@@ -1969,8 +2045,8 @@ load_settings_from_bearer (MMBearerQmi *self,
GError **error)
{
MMBearerAllowedAuth bearer_auth;
MMBearerIpFamily ip_family;
GError *inner_error = NULL;
const gchar *str;
/* If no multiplex setting given by the user, assume requested */
ctx->multiplex = mm_bearer_properties_get_multiplex (properties);
@@ -1983,6 +2059,22 @@ load_settings_from_bearer (MMBearerQmi *self,
ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem)));
}
/* If profile id is given, we'll launch the connection specifying the profile id in use
* exclusively, so we ignore any additional user provided setting */
ctx->profile_id = mm_bearer_properties_get_profile_id (properties);
if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
/* Is this a 3GPP2 only modem and profile id was given? If so, error, as we don't support
* 3GPP2 profiles in ModemManager */
if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (modem))) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
"3GPP2 doesn't support profile id setting");
return FALSE;
}
/* All done now, we'll need to load IP type settings later on once
* we load the real profile to use */
return TRUE;
}
/* APN settings */
ctx->apn = g_strdup (mm_bearer_properties_get_apn (properties));
/* Is this a 3GPP only modem and no APN was given? If so, error */
@@ -1999,29 +2091,17 @@ load_settings_from_bearer (MMBearerQmi *self,
}
/* IP type settings */
ip_family = mm_bearer_properties_get_ip_type (properties);
if (mm_3gpp_normalize_ip_family (&ip_family))
ctx->no_ip_family_preference = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV4)
ctx->ipv4 = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV6)
ctx->ipv6 = TRUE;
if (ip_family & MM_BEARER_IP_FAMILY_IPV4V6) {
ctx->ipv4 = TRUE;
ctx->ipv6 = TRUE;
}
if (!ctx->ipv4 && !ctx->ipv6) {
g_autofree gchar *str = NULL;
str = mm_bearer_ip_family_build_string_from_mask (ip_family);
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Unsupported IP type requested: '%s'", str);
if (!load_ip_type_settings_from_profile (ctx, mm_bearer_properties_peek_3gpp_profile (properties), error))
return FALSE;
}
/* Auth settings */
ctx->user = g_strdup (mm_bearer_properties_get_user (properties));
ctx->password = g_strdup (mm_bearer_properties_get_password (properties));
/* Auth settings; in we treat user/password empty strings as no strings */
str = mm_bearer_properties_get_user (properties);
if (str && str[0])
ctx->user = g_strdup (str);
str = mm_bearer_properties_get_password (properties);
if (str && str[0])
ctx->password = g_strdup (str);
if (!ctx->user && !ctx->password)
ctx->auth = QMI_WDS_AUTHENTICATION_NONE;
else {