mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-19 20:08:36 +03:00
utils: add EF [H|O]PLMNwAcT decoding.
Allow decoding and pretty printing of PLMNwAcT, HPLMNwAcT and OPLMNwAct. Includes unit tests for the added functions. Change-Id: I9b8ca6ffd98f665690b84239d9a228e2c72c6ff9
This commit is contained in:
committed by
Harald Welte
parent
91d4ec7e7b
commit
851e9c0f4c
@@ -113,6 +113,79 @@ def enc_spn(name, hplmn_disp=False, oplmn_disp=False):
|
||||
if oplmn_disp: byte1 = byte1|0x02
|
||||
return i2h([byte1])+s2h(name)
|
||||
|
||||
def hexstr_to_fivebytearr(s):
|
||||
return [s[i:i+10] for i in range(0, len(s), 10) ]
|
||||
|
||||
# Accepts hex string representing three bytes
|
||||
def dec_mcc_from_plmn(plmn):
|
||||
ia = h2i(plmn)
|
||||
digit1 = ia[0] & 0x0F # 1st byte, LSB
|
||||
digit2 = (ia[0] & 0xF0) >> 4 # 1st byte, MSB
|
||||
digit3 = ia[1] & 0x0F # 2nd byte, LSB
|
||||
if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF:
|
||||
return 0xFFF # 4095
|
||||
mcc = digit1 * 100
|
||||
mcc += digit2 * 10
|
||||
mcc += digit3
|
||||
return mcc
|
||||
|
||||
def dec_mnc_from_plmn(plmn):
|
||||
ia = h2i(plmn)
|
||||
digit1 = ia[2] & 0x0F # 3rd byte, LSB
|
||||
digit2 = (ia[2] & 0xF0) >> 4 # 3rd byte, MSB
|
||||
digit3 = (ia[1] & 0xF0) >> 4 # 2nd byte, MSB
|
||||
if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF:
|
||||
return 0xFFF # 4095
|
||||
mnc = 0
|
||||
# signifies two digit MNC
|
||||
if digit3 == 0xF:
|
||||
mnc += digit1 * 10
|
||||
mnc += digit2
|
||||
else:
|
||||
mnc += digit1 * 100
|
||||
mnc += digit2 * 10
|
||||
mnc += digit3
|
||||
return mnc
|
||||
|
||||
def dec_act(twohexbytes):
|
||||
act_list = [
|
||||
{'bit': 15, 'name': "UTRAN"},
|
||||
{'bit': 14, 'name': "E-UTRAN"},
|
||||
{'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 = []
|
||||
for a in act_list:
|
||||
if u16t & (1 << a['bit']):
|
||||
sel.append(a['name'])
|
||||
return sel
|
||||
|
||||
def dec_xplmn_w_act(fivehexbytes):
|
||||
res = {'mcc': 0, 'mnc': 0, 'act': []}
|
||||
plmn_chars = 6
|
||||
act_chars = 4
|
||||
plmn_str = fivehexbytes[:plmn_chars] # first three bytes (six ascii hex chars)
|
||||
act_str = fivehexbytes[plmn_chars:plmn_chars + act_chars] # two bytes after first three bytes
|
||||
res['mcc'] = dec_mcc_from_plmn(plmn_str)
|
||||
res['mnc'] = dec_mnc_from_plmn(plmn_str)
|
||||
res['act'] = dec_act(act_str)
|
||||
return res
|
||||
|
||||
def format_xplmn_w_act(hexstr):
|
||||
s = ""
|
||||
for rec_data in hexstr_to_fivebytearr(hexstr):
|
||||
rec_info = dec_xplmn_w_act(rec_data)
|
||||
if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF:
|
||||
rec_str = "unused"
|
||||
else:
|
||||
rec_str = "MCC: %3s MNC: %3s AcT: %s" % (rec_info['mcc'], rec_info['mnc'], ", ".join(rec_info['act']))
|
||||
s += "\t%s # %s\n" % (rec_data, rec_str)
|
||||
return s
|
||||
|
||||
def derive_milenage_opc(ki_hex, op_hex):
|
||||
"""
|
||||
Run the milenage algorithm to calculate OPC from Ki and OP
|
||||
|
||||
76
pySim/utils_test.py
Normal file
76
pySim/utils_test.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/pyton
|
||||
|
||||
import unittest
|
||||
import utils
|
||||
|
||||
class DecTestCase(unittest.TestCase):
|
||||
|
||||
def testSplitHexStringToListOf5ByteEntries(self):
|
||||
input_str = "ffffff0003ffffff0002ffffff0001"
|
||||
expected = [
|
||||
"ffffff0003",
|
||||
"ffffff0002",
|
||||
"ffffff0001",
|
||||
]
|
||||
self.assertEqual(utils.hexstr_to_fivebytearr(input_str), expected)
|
||||
|
||||
def testDecMCCfromPLMN(self):
|
||||
self.assertEqual(utils.dec_mcc_from_plmn("92f501"), 295)
|
||||
|
||||
def testDecMCCfromPLMN_unused(self):
|
||||
self.assertEqual(utils.dec_mcc_from_plmn("ff0f00"), 4095)
|
||||
|
||||
def testDecMNCfromPLMN_twoDigitMNC(self):
|
||||
self.assertEqual(utils.dec_mnc_from_plmn("92f501"), 10)
|
||||
|
||||
def testDecMNCfromPLMN_threeDigitMNC(self):
|
||||
self.assertEqual(utils.dec_mnc_from_plmn("031263"), 361)
|
||||
|
||||
def testDecMNCfromPLMN_unused(self):
|
||||
self.assertEqual(utils.dec_mnc_from_plmn("00f0ff"), 4095)
|
||||
|
||||
def testDecAct_noneSet(self):
|
||||
self.assertEqual(utils.dec_act("0000"), [])
|
||||
|
||||
def testDecAct_onlyUtran(self):
|
||||
self.assertEqual(utils.dec_act("8000"), ["UTRAN"])
|
||||
|
||||
def testDecAct_onlyEUtran(self):
|
||||
self.assertEqual(utils.dec_act("4000"), ["E-UTRAN"])
|
||||
|
||||
def testDecAct_onlyGsm(self):
|
||||
self.assertEqual(utils.dec_act("0080"), ["GSM"])
|
||||
|
||||
def testDecAct_onlyGsmCompact(self):
|
||||
self.assertEqual(utils.dec_act("0040"), ["GSM COMPACT"])
|
||||
|
||||
def testDecAct_onlyCdma2000HRPD(self):
|
||||
self.assertEqual(utils.dec_act("0020"), ["cdma2000 HRPD"])
|
||||
|
||||
def testDecAct_onlyCdma20001xRTT(self):
|
||||
self.assertEqual(utils.dec_act("0010"), ["cdma2000 1xRTT"])
|
||||
|
||||
def testDecAct_allSet(self):
|
||||
self.assertEqual(utils.dec_act("ffff"), ["UTRAN", "E-UTRAN", "GSM", "GSM COMPACT", "cdma2000 HRPD", "cdma2000 1xRTT"])
|
||||
|
||||
def testDecxPlmn_w_act(self):
|
||||
expected = {'mcc': 295, 'mnc': 10, 'act': ["UTRAN"]}
|
||||
self.assertEqual(utils.dec_xplmn_w_act("92f5018000"), expected)
|
||||
|
||||
def testFormatxPlmn_w_act(self):
|
||||
input_str = "92f501800092f5508000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000"
|
||||
expected = '''92f5018000 # MCC: 295 MNC: 10 AcT: UTRAN
|
||||
92f5508000 # MCC: 295 MNC: 5 AcT: UTRAN
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
ffffff0000 # unused
|
||||
'''
|
||||
self.assertEqual(utils.format_xplmn_w_act(input_str), expected)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user