libmm-glib,bearer-properties: allow loose comparisons

When comparing bearer properties provided by the user versus loaded
from the modem, we shouldn't be very strict, e.g.:
 * Password or other fields may not be readable from the device.
 * Some fields may not apply at all (e.g. RM protocol for EPS bearers)
 * NULL strings could be assumed equal to empty strings.
 * If no explicit IP type specified, an IPv4 default may be assumed.
 * If no explicit allowed auth specified, 'none' default may be
   assumed.

These loose comparisons are applied when managing the initial EPS
bearer settings and status, and we keep the strict comparison only
during the connection attempt lookup of a bearer with certain
settings, as those bearer objects are all created in the same place
with the same rules.
This commit is contained in:
Aleksander Morgado
2020-11-30 21:51:32 +01:00
parent c99cc9210e
commit 5629f47a59
4 changed files with 123 additions and 20 deletions

View File

@@ -667,21 +667,102 @@ mm_bearer_properties_new_from_dictionary (GVariant *dictionary,
/*****************************************************************************/ /*****************************************************************************/
static gboolean
cmp_str (const gchar *a,
const gchar *b,
MMBearerPropertiesCmpFlags flags)
{
/* Strict match */
if ((!a && !b) || (a && b && g_strcmp0 (a, b) == 0))
return TRUE;
/* Additional loose match, consider NULL and EMPTY string equal */
if (flags & MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE) {
if ((!a && !b[0]) || (!b && !a[0]))
return TRUE;
}
return FALSE;
}
static gboolean
cmp_ip_type (MMBearerIpFamily a,
MMBearerIpFamily b,
MMBearerPropertiesCmpFlags flags)
{
/* Strict match */
if (a == b)
return TRUE;
/* Additional loose match NONE == IPV4 */
if (flags & MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE) {
if ((a == MM_BEARER_IP_FAMILY_NONE && b == MM_BEARER_IP_FAMILY_IPV4) ||
(b == MM_BEARER_IP_FAMILY_NONE && a == MM_BEARER_IP_FAMILY_IPV4))
return TRUE;
}
return FALSE;
}
static gboolean
cmp_allowed_auth (MMBearerAllowedAuth a,
MMBearerAllowedAuth b,
MMBearerPropertiesCmpFlags flags)
{
/* Strict match */
if (a == b)
return TRUE;
/* Additional loose match UNKNOWN == NONE */
if (flags & MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE) {
if ((a == MM_BEARER_ALLOWED_AUTH_UNKNOWN && b == MM_BEARER_ALLOWED_AUTH_NONE) ||
(b == MM_BEARER_ALLOWED_AUTH_UNKNOWN && a == MM_BEARER_ALLOWED_AUTH_NONE))
return TRUE;
}
return FALSE;
}
static gboolean
cmp_allow_roaming (gboolean a,
gboolean a_set,
gboolean b,
gboolean b_set,
MMBearerPropertiesCmpFlags flags)
{
/* Strict match */
if (a == b && a_set == b_set)
return TRUE;
/* Additional loose match UNSET == */
if (flags & MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE) {
if ((a == MM_BEARER_ALLOWED_AUTH_UNKNOWN && b == MM_BEARER_ALLOWED_AUTH_NONE) ||
(b == MM_BEARER_ALLOWED_AUTH_UNKNOWN && a == MM_BEARER_ALLOWED_AUTH_NONE))
return TRUE;
}
return FALSE;
}
/** /**
* mm_bearer_properties_cmp: (skip) * mm_bearer_properties_cmp: (skip)
*/ */
gboolean gboolean
mm_bearer_properties_cmp (MMBearerProperties *a, mm_bearer_properties_cmp (MMBearerProperties *a,
MMBearerProperties *b) MMBearerProperties *b,
MMBearerPropertiesCmpFlags flags)
{ {
return ((!g_strcmp0 (a->priv->apn, b->priv->apn)) && if (!cmp_str (a->priv->apn, b->priv->apn, flags))
(a->priv->ip_type == b->priv->ip_type) && return FALSE;
(a->priv->allowed_auth == b->priv->allowed_auth) && if (!cmp_ip_type (a->priv->ip_type, b->priv->ip_type, flags))
(!g_strcmp0 (a->priv->user, b->priv->user)) && return FALSE;
(!g_strcmp0 (a->priv->password, b->priv->password)) && if (!cmp_allowed_auth (a->priv->allowed_auth, a->priv->allowed_auth, flags))
(a->priv->allow_roaming == b->priv->allow_roaming) && return FALSE;
(a->priv->allow_roaming_set == b->priv->allow_roaming_set) && if (!cmp_str (a->priv->user, b->priv->user, flags))
(a->priv->rm_protocol == b->priv->rm_protocol)); return FALSE;
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD) && !cmp_str (a->priv->password, b->priv->password, flags))
return FALSE;
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_ALLOW_ROAMING)) {
if (a->priv->allow_roaming != b->priv->allow_roaming)
return FALSE;
if (a->priv->allow_roaming_set != b->priv->allow_roaming)
return FALSE;
}
if (a->priv->rm_protocol != b->priv->rm_protocol)
return FALSE;
return TRUE;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@@ -113,8 +113,17 @@ gboolean mm_bearer_properties_consume_variant (MMBearerProperties *properties,
GVariant *mm_bearer_properties_get_dictionary (MMBearerProperties *self); GVariant *mm_bearer_properties_get_dictionary (MMBearerProperties *self);
gboolean mm_bearer_properties_cmp (MMBearerProperties *a, typedef enum {
MMBearerProperties *b); MM_BEARER_PROPERTIES_CMP_FLAGS_NONE = 0,
MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE = 1 << 0,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD = 1 << 1,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_ALLOW_ROAMING = 1 << 2,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_RM_PROTOCOL = 1 << 3,
} MMBearerPropertiesCmpFlags;
gboolean mm_bearer_properties_cmp (MMBearerProperties *a,
MMBearerProperties *b,
MMBearerPropertiesCmpFlags flags);
#endif #endif

View File

@@ -153,7 +153,11 @@ mm_bearer_list_find_by_properties (MMBearerList *self,
GList *l; GList *l;
for (l = self->priv->bearers; l; l = g_list_next (l)) { for (l = self->priv->bearers; l; l = g_list_next (l)) {
if (mm_bearer_properties_cmp (mm_base_bearer_peek_config (MM_BASE_BEARER (l->data)), props)) /* always strict matching when comparing these bearer properties, as they're all
* built in the same place */
if (mm_bearer_properties_cmp (mm_base_bearer_peek_config (MM_BASE_BEARER (l->data)),
props,
MM_BEARER_PROPERTIES_CMP_FLAGS_NONE))
return g_object_ref (l->data); return g_object_ref (l->data);
} }

View File

@@ -30,6 +30,16 @@
#define SUBSYSTEM_3GPP "3gpp" #define SUBSYSTEM_3GPP "3gpp"
/* When comparing EPS bearer settings take into account that PASSWORD may not always
* be readable, and apply very loose matching for all fields. Also, some implementations
* may allow configuring roaming allowance in the initial EPS bearer, but that is also
* not common. */
#define MM_BEARER_PROPERTIES_CMP_FLAGS_EPS \
(MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE | \
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD | \
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_ALLOW_ROAMING | \
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_RM_PROTOCOL)
/*****************************************************************************/ /*****************************************************************************/
/* Private data context */ /* Private data context */
@@ -1029,7 +1039,7 @@ after_set_load_initial_eps_bearer_settings_ready (MMIfaceModem3gpp
mm_obj_dbg (self, "Updated initial EPS bearer settings:"); mm_obj_dbg (self, "Updated initial EPS bearer settings:");
log_initial_eps_bearer_settings (self, new_config); log_initial_eps_bearer_settings (self, new_config);
if (!mm_bearer_properties_cmp (new_config, ctx->config)) { if (!mm_bearer_properties_cmp (new_config, ctx->config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
mm_obj_dbg (self, "Requested initial EPS bearer settings:"); mm_obj_dbg (self, "Requested initial EPS bearer settings:");
log_initial_eps_bearer_settings (self, ctx->config); log_initial_eps_bearer_settings (self, ctx->config);
g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, g_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
@@ -1108,15 +1118,11 @@ set_initial_eps_bearer_settings_auth_ready (MMBaseModem
return; return;
} }
/* If the user doesn't specify explicit auth settings, assume NONE as default */
if (mm_bearer_properties_get_allowed_auth (ctx->config) == MM_BEARER_ALLOWED_AUTH_UNKNOWN)
mm_bearer_properties_set_allowed_auth (ctx->config, MM_BEARER_ALLOWED_AUTH_NONE);
old_dictionary = mm_gdbus_modem3gpp_get_initial_eps_bearer_settings (ctx->skeleton); old_dictionary = mm_gdbus_modem3gpp_get_initial_eps_bearer_settings (ctx->skeleton);
if (old_dictionary) if (old_dictionary)
old_config = mm_bearer_properties_new_from_dictionary (old_dictionary, NULL); old_config = mm_bearer_properties_new_from_dictionary (old_dictionary, NULL);
if (old_config && mm_bearer_properties_cmp (ctx->config, old_config)) { if (old_config && mm_bearer_properties_cmp (ctx->config, old_config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
mm_gdbus_modem3gpp_complete_set_initial_eps_bearer_settings (ctx->skeleton, ctx->invocation); mm_gdbus_modem3gpp_complete_set_initial_eps_bearer_settings (ctx->skeleton, ctx->invocation);
handle_set_initial_eps_bearer_settings_context_free (ctx); handle_set_initial_eps_bearer_settings_context_free (ctx);
} else { } else {
@@ -1756,7 +1762,10 @@ mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self,
/* skip update? */ /* skip update? */
if ((!old_bearer && !properties) || if ((!old_bearer && !properties) ||
(old_bearer && properties && mm_bearer_properties_cmp (properties, mm_base_bearer_peek_config (MM_BASE_BEARER (old_bearer))))) (old_bearer && properties &&
mm_bearer_properties_cmp (properties,
mm_base_bearer_peek_config (MM_BASE_BEARER (old_bearer)),
MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)))
goto out; goto out;
if (properties) { if (properties) {