aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant/interworking.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2013-07-08 13:53:05 (GMT)
committerJouni Malinen <j@w1.fi>2013-07-08 13:53:05 (GMT)
commit0b9d3b22c8b72f1008bcb9c94571cb4c8bbfb1c7 (patch)
treed70adf5d668fc6051a99564604d86976b67e75d9 /wpa_supplicant/interworking.c
parentc7a67a77195464d667d6f482777a75325b6f3642 (diff)
downloadhostap-0b9d3b22c8b72f1008bcb9c94571cb4c8bbfb1c7.zip
hostap-0b9d3b22c8b72f1008bcb9c94571cb4c8bbfb1c7.tar.gz
hostap-0b9d3b22c8b72f1008bcb9c94571cb4c8bbfb1c7.tar.bz2
Interworking: Relax 3GPP info PLMN matching for MNC
3GPP TS 24.232 Annex A.3 allows network operator to advertise only two digits of MNC even if MNC has three digits. Allow such matches in network selection. In addition, allow three digit matches of MNC even if MNC length was assumed to be two to avoid missing networks if MNC length cannot be determined reliably. Remove the '-' separator from simulated SIM/USIM cases to allow the new matching rules to work. Fix the PLMN List information element parsing loop to use the length of the PLMN List instead of the length of the full 3GPP Cellular Info to avoid unexpected matches should a new element ever be added by 3GPP. Finally, add more debug prints from PLMN matching to make the logs easier to understand. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'wpa_supplicant/interworking.c')
-rw-r--r--wpa_supplicant/interworking.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 2f35240..36f75a1 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -599,19 +599,29 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_cred *cred,
static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
{
- u8 plmn[3];
+ u8 plmn[3], plmn2[3];
const u8 *pos, *end;
u8 udhl;
- /* See Annex A of 3GPP TS 24.234 v8.1.0 for description */
+ /*
+ * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network
+ * operator is allowed to include only two digits of the MNC, so allow
+ * matches based on both two and three digit MNC assumptions. Since some
+ * SIM/USIM cards may not expose MNC length conveniently, we may be
+ * provided the default MNC length 3 here and as such, checking with MNC
+ * length 2 is justifiable even though 3GPP TS 24.234 does not mention
+ * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used
+ * with otherwise matching values would not be good idea in general, so
+ * this should not result in selecting incorrect networks.
+ */
+ /* Match with 3 digit MNC */
plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
- plmn[1] = imsi[2] - '0';
- /* default to MNC length 3 if unknown */
- if (mnc_len != 2)
- plmn[1] |= (imsi[5] - '0') << 4;
- else
- plmn[1] |= 0xf0;
+ plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4);
plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
+ /* Match with 2 digit MNC */
+ plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
+ plmn2[1] = (imsi[2] - '0') | 0xf0;
+ plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
if (anqp == NULL)
return 0;
@@ -631,6 +641,10 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
}
end = pos + udhl;
+ wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)",
+ plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2],
+ imsi, mnc_len);
+
while (pos + 2 <= end) {
u8 iei, len;
const u8 *l_end;
@@ -643,14 +657,20 @@ static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
if (iei == 0 && len > 0) {
/* PLMN List */
u8 num, i;
+ wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element",
+ pos, len);
num = *pos++;
for (i = 0; i < num; i++) {
- if (pos + 3 > end)
+ if (pos + 3 > l_end)
break;
- if (os_memcmp(pos, plmn, 3) == 0)
+ if (os_memcmp(pos, plmn, 3) == 0 ||
+ os_memcmp(pos, plmn2, 3) == 0)
return 1; /* Found matching PLMN */
pos += 3;
}
+ } else {
+ wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element",
+ pos, len);
}
pos = l_end;
@@ -1337,6 +1357,8 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
char *sep;
const char *imsi;
int mnc_len;
+ char imsi_buf[16];
+ size_t msin_len;
#ifdef PCSC_FUNCS
if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard &&
@@ -1363,7 +1385,14 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
(sep - cred->imsi != 5 && sep - cred->imsi != 6))
continue;
mnc_len = sep - cred->imsi - 3;
- imsi = cred->imsi;
+ os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len);
+ sep++;
+ msin_len = os_strlen(cred->imsi);
+ if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1)
+ msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1;
+ os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len);
+ imsi_buf[3 + mnc_len + msin_len] = '\0';
+ imsi = imsi_buf;
#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
compare: