From 542dbf67716f5486dba612ab94da07b6a812599f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 21 Dec 2023 20:14:48 +0100 Subject: fix encode/decode of xPLMNwAcT There are some pretty intricate rules about how GSM and E-UTRAN are encoded, let's make sure we fully support both as per 3GPP TS 31.102 Release 17. As part of this, switch to a sorted list of access technologies, in order to have a defined order. This makes comparing in unit tests much easier. However, it also means that we need to sort the set when printing the list of AcT in pySim-read to generate deterministic output. Change-Id: I398ac2a2527bd11e9c652e49fa46d6ca8d334b88 --- pySim/ts_51_011.py | 10 +++--- pySim/utils.py | 40 +++++++++++++----------- pysim-testdata/Fairwaves-SIM.ok | 2 +- pysim-testdata/Wavemobile-SIM.ok | 4 +-- pysim-testdata/pySim-trace_test_gsmtap.pcapng.ok | 6 ++-- pysim-testdata/sysmoISIM-SJA2.ok | 6 ++-- pysim-testdata/sysmoUSIM-SJS1.ok | 6 ++-- tests/test_utils.py | 6 ++-- 8 files changed, 42 insertions(+), 38 deletions(-) diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 7413098..65bc85c 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -728,7 +728,7 @@ class EF_LOCIGPRS(TransparentEF): # TS 51.011 Section 10.3.35..37 class EF_xPLMNwAcT(TransRecEF): _test_de_encode = [ - ( '62F2104000', { "mcc": "262", "mnc": "01", "act": [ "E-UTRAN" ] } ), + ( '62F2104000', { "mcc": "262", "mnc": "01", "act": [ "E-UTRAN NB-S1", "E-UTRAN WB-S1" ] } ), ( '62F2108000', { "mcc": "262", "mnc": "01", "act": [ "UTRAN" ] } ), ] def __init__(self, fid='1234', sfid=None, name=None, desc=None, size=(40, None), rec_len=5, **kwargs): @@ -763,18 +763,18 @@ class EF_xPLMNwAcT(TransRecEF): if 'cdma2000 1xRTT' in in_list: u16 |= 0x0010 # E-UTRAN - if 'E-UTRAN' in in_list: + if 'E-UTRAN WB-S1' in in_list and 'E-UTRAN NB-S1' in in_list: u16 |= 0x4000 - if 'E-UTRAN WB-S1' in in_list: + elif 'E-UTRAN WB-S1' in in_list: u16 |= 0x6000 - if 'E-UTRAN NB-S1' in in_list: + elif 'E-UTRAN NB-S1' in in_list: u16 |= 0x5000 # GSM mess if 'GSM' in in_list and 'EC-GSM-IoT' in in_list: u16 |= 0x008C elif 'GSM' in in_list: u16 |= 0x0084 - elif 'EC-GSM-IuT' in in_list: + elif 'EC-GSM-IoT' in in_list: u16 |= 0x0088 return '%04X' % (u16) diff --git a/pySim/utils.py b/pySim/utils.py index aac9877..6523d98 100644 --- a/pySim/utils.py +++ b/pySim/utils.py @@ -486,33 +486,37 @@ def dec_mnc_from_plmn_str(plmn: Hexstr) -> str: def dec_act(twohexbytes: Hexstr) -> List[str]: act_list = [ {'bit': 15, 'name': "UTRAN"}, - {'bit': 14, 'name': "E-UTRAN"}, {'bit': 11, 'name': "NG-RAN"}, - {'bit': 7, 'name': "GSM"}, {'bit': 6, 'name': "GSM COMPACT"}, {'bit': 5, 'name': "cdma2000 HRPD"}, {'bit': 4, 'name': "cdma2000 1xRTT"}, ] ia = h2i(twohexbytes) u16t = (ia[0] << 8) | ia[1] - sel = [] + sel = set() + # only the simple single-bit ones for a in act_list: if u16t & (1 << a['bit']): - if a['name'] == "E-UTRAN": - # The Access technology identifier of E-UTRAN - # allows a more detailed specification: - if u16t & (1 << 13) and u16t & (1 << 12): - sel.append("E-UTRAN WB-S1") - sel.append("E-UTRAN NB-S1") - elif u16t & (1 << 13): - sel.append("E-UTRAN WB-S1") - elif u16t & (1 << 12): - sel.append("E-UTRAN NB-S1") - else: - sel.append("E-UTRAN") - else: - sel.append(a['name']) - return sel + sel.add(a['name']) + # TS 31.102 Section 4.2.5 Table 4.2.5.1 + eutran_bits = u16t & 0x7000 + if eutran_bits == 0x4000 or eutran_bits == 0x7000: + sel.add("E-UTRAN WB-S1") + sel.add("E-UTRAN NB-S1") + elif eutran_bits == 0x5000: + sel.add("E-UTRAN NB-S1") + elif eutran_bits == 0x6000: + sel.add("E-UTRAN WB-S1") + # TS 31.102 Section 4.2.5 Table 4.2.5.2 + gsm_bits = u16t & 0x008C + if gsm_bits == 0x0080 or gsm_bits == 0x008C: + sel.add("GSM") + sel.add("EC-GSM-IoT") + elif u16t & 0x008C == 0x0084: + sel.add("GSM") + elif u16t & 0x008C == 0x0086: + sel.add("EC-GSM-IoT") + return sorted(list(sel)) def dec_xplmn_w_act(fivehexbytes: Hexstr) -> Dict[str, Any]: diff --git a/pysim-testdata/Fairwaves-SIM.ok b/pysim-testdata/Fairwaves-SIM.ok index 063fc6b..3751c57 100644 --- a/pysim-testdata/Fairwaves-SIM.ok +++ b/pysim-testdata/Fairwaves-SIM.ok @@ -31,7 +31,7 @@ OPLMNwAcT: ffffff0000 # unused HPLMNAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused diff --git a/pysim-testdata/Wavemobile-SIM.ok b/pysim-testdata/Wavemobile-SIM.ok index 980332f..7a0ecec 100644 --- a/pysim-testdata/Wavemobile-SIM.ok +++ b/pysim-testdata/Wavemobile-SIM.ok @@ -11,7 +11,7 @@ Show in HPLMN: False Hide in OPLMN: False PLMNsel: 00f110ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused @@ -29,7 +29,7 @@ PLMNwAcT: ffffff0000 # unused OPLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused diff --git a/pysim-testdata/pySim-trace_test_gsmtap.pcapng.ok b/pysim-testdata/pySim-trace_test_gsmtap.pcapng.ok index 600c36d..873574c 100644 --- a/pysim-testdata/pySim-trace_test_gsmtap.pcapng.ok +++ b/pysim-testdata/pySim-trace_test_gsmtap.pcapng.ok @@ -89,11 +89,11 @@ CardReset(3b9f96801f878031e073fe211b674a4c753034054ba9) =============================== 00 READ BINARY MF/ADF.USIM/EF.HPPLMN - 9000 5 =============================== -00 READ BINARY MF/ADF.USIM/EF.HPLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['UTRAN', 'E-UTRAN WB-S1', 'E-UTRAN NB-S1', 'NG-RAN', 'GSM', 'GSM COMPACT', 'cdma2000 HRPD', 'cdma2000 1xRTT']}, None, None, None, None, None, None, None, None, None, None, None] +00 READ BINARY MF/ADF.USIM/EF.HPLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['E-UTRAN NB-S1', 'E-UTRAN WB-S1', 'EC-GSM-IoT', 'GSM', 'GSM COMPACT', 'NG-RAN', 'UTRAN', 'cdma2000 1xRTT', 'cdma2000 HRPD']}, None, None, None, None, None, None, None, None, None, None, None] =============================== -00 READ BINARY MF/ADF.USIM/EF.PLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['UTRAN', 'E-UTRAN WB-S1', 'E-UTRAN NB-S1', 'NG-RAN', 'GSM', 'GSM COMPACT', 'cdma2000 HRPD', 'cdma2000 1xRTT']}, None, None, None, None, None, None, None, None, None, None, None] +00 READ BINARY MF/ADF.USIM/EF.PLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['E-UTRAN NB-S1', 'E-UTRAN WB-S1', 'EC-GSM-IoT', 'GSM', 'GSM COMPACT', 'NG-RAN', 'UTRAN', 'cdma2000 1xRTT', 'cdma2000 HRPD']}, None, None, None, None, None, None, None, None, None, None, None] =============================== -00 READ BINARY MF/ADF.USIM/EF.OPLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['UTRAN', 'E-UTRAN WB-S1', 'E-UTRAN NB-S1', 'NG-RAN', 'GSM', 'GSM COMPACT', 'cdma2000 HRPD', 'cdma2000 1xRTT']}, None, None, None, None, None, None, None, None, None, None, None] +00 READ BINARY MF/ADF.USIM/EF.OPLMNwAcT - 9000 [{'mcc': '001', 'mnc': '01', 'act': ['E-UTRAN NB-S1', 'E-UTRAN WB-S1', 'EC-GSM-IoT', 'GSM', 'GSM COMPACT', 'NG-RAN', 'UTRAN', 'cdma2000 1xRTT', 'cdma2000 HRPD']}, None, None, None, None, None, None, None, None, None, None, None] =============================== 00 READ BINARY MF/ADF.USIM/EF.FPLMN - 9000 [{'mcc': '262', 'mnc': '01'}, {'mcc': '262', 'mnc': '02'}, {'mcc': '262', 'mnc': '03'}, None] =============================== diff --git a/pysim-testdata/sysmoISIM-SJA2.ok b/pysim-testdata/sysmoISIM-SJA2.ok index 45acd79..5640171 100644 --- a/pysim-testdata/sysmoISIM-SJA2.ok +++ b/pysim-testdata/sysmoISIM-SJA2.ok @@ -11,7 +11,7 @@ Show in HPLMN: True Hide in OPLMN: True PLMNsel: 00f110ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused @@ -25,7 +25,7 @@ PLMNwAcT: ffffff0000 # unused OPLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused @@ -39,7 +39,7 @@ OPLMNwAcT: ffffff0000 # unused HPLMNAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused diff --git a/pysim-testdata/sysmoUSIM-SJS1.ok b/pysim-testdata/sysmoUSIM-SJS1.ok index b793cc0..c909a89 100644 --- a/pysim-testdata/sysmoUSIM-SJS1.ok +++ b/pysim-testdata/sysmoUSIM-SJS1.ok @@ -11,7 +11,7 @@ Show in HPLMN: True Hide in OPLMN: True PLMNsel: 00f110ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused @@ -25,7 +25,7 @@ PLMNwAcT: ffffff0000 # unused OPLMNwAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused @@ -39,7 +39,7 @@ OPLMNwAcT: ffffff0000 # unused HPLMNAcT: - 00f110ffff # MCC: 001 MNC: 01 AcT: UTRAN, E-UTRAN WB-S1, E-UTRAN NB-S1, NG-RAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT + 00f110ffff # MCC: 001 MNC: 01 AcT: E-UTRAN NB-S1, E-UTRAN WB-S1, EC-GSM-IoT, GSM, GSM COMPACT, NG-RAN, UTRAN, cdma2000 1xRTT, cdma2000 HRPD ffffff0000 # unused ffffff0000 # unused ffffff0000 # unused diff --git a/tests/test_utils.py b/tests/test_utils.py index 764cf71..062b614 100755 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -95,13 +95,13 @@ class DecTestCase(unittest.TestCase): self.assertEqual(utils.dec_act("8000"), ["UTRAN"]) def testDecAct_onlyEUtran(self): - self.assertEqual(utils.dec_act("4000"), ["E-UTRAN"]) + self.assertEqual(utils.dec_act("4000"), ["E-UTRAN NB-S1", "E-UTRAN WB-S1"]) def testDecAct_onlyNgRan(self): self.assertEqual(utils.dec_act("0800"), ["NG-RAN"]) def testDecAct_onlyGsm(self): - self.assertEqual(utils.dec_act("0080"), ["GSM"]) + self.assertEqual(utils.dec_act("0084"), ["GSM"]) def testDecAct_onlyGsmCompact(self): self.assertEqual(utils.dec_act("0040"), ["GSM COMPACT"]) @@ -113,7 +113,7 @@ class DecTestCase(unittest.TestCase): self.assertEqual(utils.dec_act("0010"), ["cdma2000 1xRTT"]) def testDecAct_allSet(self): - self.assertEqual(utils.dec_act("ffff"), ["UTRAN", "E-UTRAN WB-S1", "E-UTRAN NB-S1", "NG-RAN", "GSM", "GSM COMPACT", "cdma2000 HRPD", "cdma2000 1xRTT"]) + self.assertEqual(utils.dec_act("ffff"), ['E-UTRAN NB-S1', 'E-UTRAN WB-S1', 'EC-GSM-IoT', 'GSM', 'GSM COMPACT', 'NG-RAN', 'UTRAN', 'cdma2000 1xRTT', 'cdma2000 HRPD']) def testDecxPlmn_w_act(self): expected = {'mcc': '295', 'mnc': '10', 'act': ["UTRAN"]} -- cgit v1.2.3