modem-helpers: implement less strict APN comparison
u-blox modems will append a string showing the MCC and MNC info to the access point name listed in AT+CGDCONT? responses. We will try to detect when that happens, and we just accept the match. The logic doesn't just look for a string prefix; it also looks for the special MCC + MNC suffix, which is much more restrictive, to try to avoid false positives.
This commit is contained in:
@@ -891,13 +891,14 @@ parse_pdp_list (MMBaseModem *modem,
|
||||
const gchar *apn;
|
||||
|
||||
apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
|
||||
if (apn && !g_ascii_strcasecmp (pdp->apn, apn)) {
|
||||
/* First requested, then existing */
|
||||
if (mm_3gpp_cmp_apn_name (apn, pdp->apn)) {
|
||||
gchar *ip_family_str;
|
||||
|
||||
/* Found a PDP context with the same CID and PDP type, we'll use it. */
|
||||
/* Found a PDP context with the same APN and PDP type, we'll use it. */
|
||||
ip_family_str = mm_bearer_ip_family_build_string_from_mask (pdp->pdp_type);
|
||||
mm_dbg ("Found PDP context with CID %u and PDP type %s for APN '%s'",
|
||||
pdp->cid, ip_family_str, pdp->apn);
|
||||
pdp->cid, ip_family_str, apn);
|
||||
cid = pdp->cid;
|
||||
ctx->use_existing_cid = TRUE;
|
||||
g_free (ip_family_str);
|
||||
|
||||
@@ -1030,6 +1030,50 @@ out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* Logic to compare two APN names */
|
||||
|
||||
gboolean
|
||||
mm_3gpp_cmp_apn_name (const gchar *requested,
|
||||
const gchar *existing)
|
||||
{
|
||||
size_t requested_len;
|
||||
size_t existing_len;
|
||||
|
||||
/* Both must be given to compare properly */
|
||||
if (!existing || !existing[0] || !requested || !requested[0])
|
||||
return FALSE;
|
||||
|
||||
requested_len = strlen (requested);
|
||||
|
||||
/*
|
||||
* 1) The requested APN should be at least the prefix of the existing one.
|
||||
*/
|
||||
if (g_ascii_strncasecmp (existing, requested, requested_len) != 0)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* 2) If the existing one is actually the same as the requested one (i.e.
|
||||
* there are no more different chars in the existing one), we're done.
|
||||
*/
|
||||
if (existing[requested_len] == '\0')
|
||||
return TRUE;
|
||||
|
||||
existing_len = strlen (existing);
|
||||
|
||||
/* 3) Special handling for PDP contexts reported by u-blox modems once the
|
||||
* contexts have been activated at least once:
|
||||
* "ac.vodafone.es.MNC001.MCC214.GPRS" should match "ac.vodafone.es"
|
||||
*/
|
||||
if ((existing_len > (requested_len + 14)) &&
|
||||
g_ascii_strncasecmp (&existing[requested_len], ".mnc", 4) == 0 &&
|
||||
g_ascii_strncasecmp (&existing[requested_len + 7], ".mcc", 4) == 0)
|
||||
return TRUE;
|
||||
|
||||
/* No match */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
|
||||
@@ -127,6 +127,10 @@ gboolean mm_3gpp_parse_cops_read_response (const gchar *response,
|
||||
MMModemAccessTechnology *out_act,
|
||||
GError **error);
|
||||
|
||||
/* Logic to compare two APN names */
|
||||
gboolean mm_3gpp_cmp_apn_name (const gchar *requested,
|
||||
const gchar *existing);
|
||||
|
||||
/* AT+CGDCONT=? (PDP context format) test parser */
|
||||
typedef struct {
|
||||
guint min_cid;
|
||||
|
||||
@@ -1821,6 +1821,43 @@ test_iccid_parse_unquoted_invalid_mii (void *f, gpointer d)
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Test APN cmp */
|
||||
|
||||
typedef struct {
|
||||
const gchar *existing;
|
||||
const gchar *requested;
|
||||
gboolean match_expected;
|
||||
} TestApnCmp;
|
||||
|
||||
static const TestApnCmp test_apn_cmp[] = {
|
||||
{ "m2m.com.attz", "m2m.com.attz", TRUE },
|
||||
{ "m2m.com.attz", "M2M.COM.ATTZ", TRUE },
|
||||
{ "M2M.COM.ATTZ", "m2m.com.attz", TRUE },
|
||||
{ "m2m.com.attz.mnc170.mcc310.gprs", "m2m.com.attz", TRUE },
|
||||
{ "ac.vodafone.es.MNC001.MCC214.GPRS", "ac.vodafone.es", TRUE },
|
||||
{ "m2m.com.attz", "m2m.com.attz.mnc170.mcc310.gprs", FALSE },
|
||||
{ "ac.vodafone.es", "ac.vodafone.es.MNC001.MCC214.GPRS", FALSE },
|
||||
{ "internet.test", "internet", FALSE },
|
||||
{ "internet.test", "INTERNET", FALSE },
|
||||
{ "internet.test", "internet.tes", FALSE },
|
||||
{ "", "", FALSE },
|
||||
};
|
||||
|
||||
static void
|
||||
test_cmp_apn_name (void)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_apn_cmp); i++) {
|
||||
g_debug ("Comparing requested '%s' vs existing '%s': %s match",
|
||||
test_apn_cmp[i].requested,
|
||||
test_apn_cmp[i].existing,
|
||||
test_apn_cmp[i].match_expected ? "should" : "shouldn't");
|
||||
g_assert (mm_3gpp_cmp_apn_name (test_apn_cmp[i].requested, test_apn_cmp[i].existing) == test_apn_cmp[i].match_expected);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Test CGDCONT test responses */
|
||||
|
||||
@@ -3456,6 +3493,8 @@ int main (int argc, char **argv)
|
||||
g_test_suite_add (suite, TESTCASE (test_cpms_response_empty_fields, NULL));
|
||||
g_test_suite_add (suite, TESTCASE (test_cpms_query_response, NULL));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_cmp_apn_name, NULL));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_single, NULL));
|
||||
g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_multiple, NULL));
|
||||
g_test_suite_add (suite, TESTCASE (test_cgdcont_test_response_multiple_and_ignore, NULL));
|
||||
|
||||
Reference in New Issue
Block a user