lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

January 2024

  • 1 participants
  • 1559 discussions
[M] Change in pysim[master]: global_platform: Implement generic store_data command
by laforge 12 Jan '24

12 Jan '24
Attention is currently required from: fixeria. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/35553?usp=email ) Change subject: global_platform: Implement generic store_data command ...................................................................... Patch Set 1: (2 comments) File pySim/global_platform.py: https://gerrit.osmocom.org/c/pysim/+/35553/comment/a545e02d_86f9431e PS1, Line 344: opts.response == 'may_be_returned' > The operator `==` already gives `True/False`, so ternary operator is redundant. Ack https://gerrit.osmocom.org/c/pysim/+/35553/comment/2e610e9f_1a71c14e PS1, Line 361: sw > Do we want to check `sw` here? the method send_apdu_checksw() already does that check internally, as the name implies. It will raise an exception if it's not a succesful SW. -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35553?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If30c5d31b4e7dd60d3a5cfb1d1cbdcf61741a50e Gerrit-Change-Number: 35553 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Fri, 12 Jan 2024 10:52:01 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
[M] Change in pysim[master]: global_platform: Implement generic store_data command
by fixeria 12 Jan '24

12 Jan '24
Attention is currently required from: laforge. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/35553?usp=email ) Change subject: global_platform: Implement generic store_data command ...................................................................... Patch Set 1: Code-Review+1 (2 comments) File pySim/global_platform.py: https://gerrit.osmocom.org/c/pysim/+/35553/comment/e3dcba3d_999be2db PS1, Line 344: opts.response == 'may_be_returned' The operator `==` already gives `True/False`, so ternary operator is redundant. https://gerrit.osmocom.org/c/pysim/+/35553/comment/409b2eab_40ae36f0 PS1, Line 361: sw Do we want to check `sw` here? -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35553?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If30c5d31b4e7dd60d3a5cfb1d1cbdcf61741a50e Gerrit-Change-Number: 35553 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Fri, 12 Jan 2024 10:18:52 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in pysim[master]: euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD
by fixeria 12 Jan '24

12 Jan '24
Attention is currently required from: laforge. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/35552?usp=email ) Change subject: euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD ...................................................................... Patch Set 1: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35552?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I660e874d9bcbb8c28a64e4ef82dc53bee97aacfc Gerrit-Change-Number: 35552 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Fri, 12 Jan 2024 10:09:24 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in pysim[master]: Constrain user input to hex-string in argparse
by fixeria 12 Jan '24

12 Jan '24
Attention is currently required from: laforge. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/pysim/+/35551?usp=email ) Change subject: Constrain user input to hex-string in argparse ...................................................................... Patch Set 1: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35551?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I6426ea864bec82be60554dd125961a48d7751904 Gerrit-Change-Number: 35551 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Fri, 12 Jan 2024 10:01:01 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in pysim[master]: euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD
by laforge 12 Jan '24

12 Jan '24
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/35552?usp=email ) Change subject: euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD ...................................................................... euicc: Migrate ECASD + ISD-R over to global_platform.CardApplicationSD Actually, the GSMA eUICC is a kind of derivative of a GlobalPlatform card, and the ECASD and ISD-R are security domains. As such, we should make them derived classes of global_platform.CardApplicationSD which means they inherit some of the shared shell_commands etc. Change-Id: I660e874d9bcbb8c28a64e4ef82dc53bee97aacfc --- M pySim/euicc.py 1 file changed, 46 insertions(+), 50 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/52/35552/1 diff --git a/pySim/euicc.py b/pySim/euicc.py index 81fbd1e..96d95d6 100644 --- a/pySim/euicc.py +++ b/pySim/euicc.py @@ -49,15 +49,6 @@ AID_ISD_P_FILE = "A0000005591010FFFFFFFF8900000D00" AID_ISD_P_MODULE = "A0000005591010FFFFFFFF8900000E00" -sw_isdr = { - 'ISD-R': { - '6a80': 'Incorrect values in command data', - '6a82': 'Profile not found', - '6a88': 'Reference data not found', - '6985': 'Conditions of use not satisfied', - } -} - class SupportedVersionNumber(BER_TLV_IE, tag=0x82): _construct = GreedyBytes @@ -286,11 +277,12 @@ class GetEimConfigurationData(BER_TLV_IE, tag=0xbf55, nested=[EimConfigurationDataSeq]): pass -class ADF_ISDR(CardADF): - def __init__(self, aid=AID_ISD_R, name='ADF.ISD-R', fid=None, sfid=None, - desc='ISD-R (Issuer Security Domain Root) Application'): - super().__init__(aid=aid, fid=fid, sfid=sfid, name=name, desc=desc) - self.shell_commands += [self.AddlShellCommands()] +class CardApplicationISDR(pySim.global_platform.CardApplicationSD): + def __init__(self): + super().__init__(name='ADF.ISD-R', aid=AID_ISD_R, + desc='ISD-R (Issuer Security Domain Root) Application') + self.adf.decode_select_response = self.decode_select_response + self.adf.shell_commands += [self.AddlShellCommands()] @staticmethod def store_data(scc: SimCardCommands, tx_do: Hexstr) -> Tuple[Hexstr, SwHexstr]: @@ -310,7 +302,7 @@ return ValueError('DO > 255 bytes not supported yet') else: cmd_do_enc = b'' - (data, sw) = ADF_ISDR.store_data(scc, b2h(cmd_do_enc)) + (data, sw) = CardApplicationISDR.store_data(scc, b2h(cmd_do_enc)) if data: if resp_cls: resp_do = resp_cls() @@ -336,11 +328,11 @@ @cmd2.with_argparser(es10x_store_data_parser) def do_es10x_store_data(self, opts): """Perform a raw STORE DATA command as defined for the ES10x eUICC interface.""" - (data, sw) = ADF_ISDR.store_data(self._cmd.lchan.scc, opts.TX_DO) + (data, sw) = CardApplicationISDR.store_data(self._cmd.lchan.scc, opts.TX_DO) def do_get_euicc_configured_addresses(self, opts): """Perform an ES10a GetEuiccConfiguredAddresses function.""" - eca = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccConfiguredAddresses(), EuiccConfiguredAddresses) + eca = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccConfiguredAddresses(), EuiccConfiguredAddresses) d = eca.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['euicc_configured_addresses'])) @@ -351,31 +343,31 @@ def do_set_default_dp_address(self, opts): """Perform an ES10a SetDefaultDpAddress function.""" sdda_cmd = SetDefaultDpAddress(children=[DefaultDpAddress(decoded=opts.DP_ADDRESS)]) - sdda = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, sdda_cmd, SetDefaultDpAddress) + sdda = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, sdda_cmd, SetDefaultDpAddress) d = sdda.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['set_default_dp_address'])) def do_get_euicc_challenge(self, opts): """Perform an ES10b GetEUICCChallenge function.""" - gec = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetEuiccChallenge(), GetEuiccChallenge) + gec = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetEuiccChallenge(), GetEuiccChallenge) d = gec.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_challenge'])) def do_get_euicc_info1(self, opts): """Perform an ES10b GetEUICCInfo (1) function.""" - ei1 = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo1(), EuiccInfo1) + ei1 = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo1(), EuiccInfo1) d = ei1.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['euicc_info1'])) def do_get_euicc_info2(self, opts): """Perform an ES10b GetEUICCInfo (2) function.""" - ei2 = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo2(), EuiccInfo2) + ei2 = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, EuiccInfo2(), EuiccInfo2) d = ei2.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['euicc_info2'])) def do_list_notification(self, opts): """Perform an ES10b ListNotification function.""" - ln = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ListNotificationReq(), ListNotificationResp) + ln = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ListNotificationReq(), ListNotificationResp) d = ln.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['list_notification_resp'])) @@ -386,13 +378,13 @@ def do_remove_notification_from_list(self, opts): """Perform an ES10b RemoveNotificationFromList function.""" rn_cmd = NotificationSentReq(children=[SeqNumber(decoded=opts.SEQ_NR)]) - rn = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, rn_cmd, NotificationSentResp) + rn = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, rn_cmd, NotificationSentResp) d = rn.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['notification_sent_resp'])) def do_get_profiles_info(self, opts): """Perform an ES10c GetProfilesInfo function.""" - pi = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ProfileInfoListReq(), ProfileInfoListResp) + pi = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ProfileInfoListReq(), ProfileInfoListResp) d = pi.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['profile_info_list_resp'])) @@ -411,7 +403,7 @@ p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)]) ep_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)] ep_cmd = EnableProfileReq(children=ep_cmd_contents) - ep = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ep_cmd, EnableProfileResp) + ep = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ep_cmd, EnableProfileResp) d = ep.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['enable_profile_resp'])) @@ -430,7 +422,7 @@ p_id = ProfileIdentifier(children=[Iccid(decoded=opts.iccid)]) dp_cmd_contents = [p_id, RefreshFlag(decoded=opts.refresh_required)] dp_cmd = DisableProfileReq(children=dp_cmd_contents) - dp = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DisableProfileResp) + dp = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DisableProfileResp) d = dp.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['disable_profile_resp'])) @@ -448,16 +440,16 @@ p_id = Iccid(decoded=opts.iccid) dp_cmd_contents = [p_id] dp_cmd = DeleteProfileReq(children=dp_cmd_contents) - dp = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DeleteProfileResp) + dp = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, dp_cmd, DeleteProfileResp) d = dp.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['delete_profile_resp'])) def do_get_eid(self, opts): """Perform an ES10c GetEID function.""" - (data, sw) = ADF_ISDR.store_data(self._cmd.lchan.scc, 'BF3E035C015A') + (data, sw) = CardApplicationISDR.store_data(self._cmd.lchan.scc, 'BF3E035C015A') ged_cmd = GetEuiccData(children=[TagList(decoded=[0x5A])]) - ged = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, ged_cmd, GetEuiccData) + ged = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, ged_cmd, GetEuiccData) d = ged.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['get_euicc_data'])) @@ -471,46 +463,36 @@ nickname = opts.profile_nickname or '' sn_cmd_contents = [Iccid(decoded=opts.ICCID), ProfileNickname(decoded=nickname)] sn_cmd = SetNicknameReq(children=sn_cmd_contents) - sn = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, sn_cmd, SetNicknameResp) + sn = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, sn_cmd, SetNicknameResp) d = sn.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['set_nickname_resp'])) def do_get_certs(self, opts): """Perform an ES10c GetCerts() function on an IoT eUICC.""" - gc = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetCertsReq(), GetCertsResp) + gc = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetCertsReq(), GetCertsResp) d = gc.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['get_certficiates_resp'])) def do_get_eim_configuration_data(self, opts): """Perform an ES10b GetEimConfigurationData function on an Iot eUICC.""" - gec = ADF_ISDR.store_data_tlv(self._cmd.lchan.scc, GetEimConfigurationData(), - GetEimConfigurationData) + gec = CardApplicationISDR.store_data_tlv(self._cmd.lchan.scc, GetEimConfigurationData(), + GetEimConfigurationData) d = gec.to_dict() self._cmd.poutput_json(flatten_dict_lists(d['get_eim_configuration_data'])) - -class ADF_ECASD(CardADF): - def __init__(self, aid=AID_ECASD, name='ADF.ECASD', fid=None, sfid=None, - desc='ECASD (eUICC Controlling Authority Security Domain) Application'): - super().__init__(aid=aid, fid=fid, sfid=sfid, name=name, desc=desc) - self.shell_commands += [self.AddlShellCommands()] - +class CardApplicationECASD(pySim.global_platform.CardApplicationSD): def decode_select_response(self, data_hex: Hexstr) -> object: t = FciTemplate() t.from_tlv(h2b(data_hex)) d = t.to_dict() return flatten_dict_lists(d['fci_template']) + def __init__(self): + super().__init__(name='ADF.ECASD', aid=AID_ECASD, + desc='ECASD (eUICC Controlling Authority Security Domain) Application') + self.adf.decode_select_response = self.decode_select_response + self.adf.shell_commands += [self.AddlShellCommands()] + @with_default_category('Application-Specific Commands') class AddlShellCommands(CommandSet): pass - - - -class CardApplicationISDR(CardApplication): - def __init__(self): - super().__init__('ISD-R', adf=ADF_ISDR(), sw=sw_isdr) - -class CardApplicationECASD(CardApplication): - def __init__(self): - super().__init__('ECASD', adf=ADF_ECASD(), sw=sw_isdr) -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35552?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I660e874d9bcbb8c28a64e4ef82dc53bee97aacfc Gerrit-Change-Number: 35552 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in pysim[master]: Constrain user input to hex-string in argparse
by laforge 12 Jan '24

12 Jan '24
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/35551?usp=email ) Change subject: Constrain user input to hex-string in argparse ...................................................................... Constrain user input to hex-string in argparse We do have an is_hexstr function which we should use anywhere where we expect the user to input a string of hex digits. This way we validate the input before running in some random exception. Change-Id: I6426ea864bec82be60554dd125961a48d7751904 --- M pySim/filesystem.py M pySim/ts_102_222.py M pySim/ts_31_102.py M pySim/ts_51_011.py 4 files changed, 31 insertions(+), 22 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/51/35551/1 diff --git a/pySim/filesystem.py b/pySim/filesystem.py index c71150a..5d1970a 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -38,7 +38,7 @@ from smartcard.util import toBytes -from pySim.utils import sw_match, h2b, b2h, i2h, is_hex, auto_int, Hexstr +from pySim.utils import sw_match, h2b, b2h, i2h, is_hex, auto_int, Hexstr, is_hexstr from pySim.construct import filter_dict, parse_construct, build_construct from pySim.exceptions import * from pySim.jsonpath import js_path_find, js_path_modify @@ -579,7 +579,7 @@ dec_hex_parser = argparse.ArgumentParser() dec_hex_parser.add_argument('--oneline', action='store_true', help='No JSON pretty-printing, dump as a single line') - dec_hex_parser.add_argument('HEXSTR', help='Hex-string of encoded data to decode') + dec_hex_parser.add_argument('HEXSTR', type=is_hexstr, help='Hex-string of encoded data to decode') @cmd2.with_argparser(dec_hex_parser) def do_decode_hex(self, opts): @@ -612,8 +612,7 @@ upd_bin_parser = argparse.ArgumentParser() upd_bin_parser.add_argument( '--offset', type=int, default=0, help='Byte offset for start of read') - upd_bin_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + upd_bin_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(upd_bin_parser) def do_update_binary(self, opts): @@ -623,8 +622,7 @@ self._cmd.poutput(data) upd_bin_dec_parser = argparse.ArgumentParser() - upd_bin_dec_parser.add_argument( - 'data', help='Abstract data (JSON format) to write') + upd_bin_dec_parser.add_argument('data', type=is_hexstr, help='Abstract data (JSON format) to write') upd_bin_dec_parser.add_argument('--json-path', type=str, help='JSON path to modify specific element of file only') @@ -802,7 +800,7 @@ dec_hex_parser = argparse.ArgumentParser() dec_hex_parser.add_argument('--oneline', action='store_true', help='No JSON pretty-printing, dump as a single line') - dec_hex_parser.add_argument('HEXSTR', help='Hex-string of encoded data to decode') + dec_hex_parser.add_argument('HEXSTR', type=is_hexstr, help='Hex-string of encoded data to decode') @cmd2.with_argparser(dec_hex_parser) def do_decode_hex(self, opts): @@ -872,8 +870,7 @@ upd_rec_parser = argparse.ArgumentParser() upd_rec_parser.add_argument( 'record_nr', type=int, help='Number of record to be read') - upd_rec_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + upd_rec_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(upd_rec_parser) def do_update_record(self, opts): @@ -885,8 +882,7 @@ upd_rec_dec_parser = argparse.ArgumentParser() upd_rec_dec_parser.add_argument( 'record_nr', type=int, help='Number of record to be read') - upd_rec_dec_parser.add_argument( - 'data', help='Abstract data (JSON format) to write') + upd_rec_dec_parser.add_argument('data', type=is_hexstr, help='Abstract data (JSON format) to write') upd_rec_dec_parser.add_argument('--json-path', type=str, help='JSON path to modify specific element of record only') @@ -1248,8 +1244,7 @@ set_data_parser = argparse.ArgumentParser() set_data_parser.add_argument( 'tag', type=auto_int, help='BER-TLV Tag of value to set') - set_data_parser.add_argument( - 'data', help='Data bytes (hex format) to write') + set_data_parser.add_argument('data', type=is_hexstr, help='Data bytes (hex format) to write') @cmd2.with_argparser(set_data_parser) def do_set_data(self, opts): diff --git a/pySim/ts_102_222.py b/pySim/ts_102_222.py index 372d67f..bf5e29f 100644 --- a/pySim/ts_102_222.py +++ b/pySim/ts_102_222.py @@ -107,7 +107,7 @@ (data, sw) = self._cmd.lchan.scc.terminate_card_usage() create_parser = argparse.ArgumentParser() - create_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string') + create_parser.add_argument('FILE_ID', type=is_hexstr, help='File Identifier as 4-character hex string') create_parser._action_groups.pop() create_required = create_parser.add_argument_group('required arguments') create_optional = create_parser.add_argument_group('optional arguments') @@ -154,7 +154,7 @@ self._cmd.lchan.select_file(self._cmd.lchan.selected_file) createdf_parser = argparse.ArgumentParser() - createdf_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string') + createdf_parser.add_argument('FILE_ID', type=is_hexstr, help='File Identifier as 4-character hex string') createdf_parser._action_groups.pop() createdf_required = createdf_parser.add_argument_group('required arguments') createdf_optional = createdf_parser.add_argument_group('optional arguments') @@ -162,7 +162,7 @@ createdf_required.add_argument('--ef-arr-file-id', required=True, type=str, help='Referenced Security: File Identifier of EF.ARR') createdf_required.add_argument('--ef-arr-record-nr', required=True, type=int, help='Referenced Security: Record Number within EF.ARR') createdf_optional.add_argument('--shareable', action='store_true', help='Should the file be shareable?') - createdf_optional.add_argument('--aid', type=str, help='Application ID (creates an ADF, instead of a DF)') + createdf_optional.add_argument('--aid', type=is_hexstr, help='Application ID (creates an ADF, instead of a DF)') # mandatory by spec, but ignored by several OS, so don't force the user createdf_optional.add_argument('--total-file-size', type=int, help='Physical memory allocated for DF/ADi in octets') createdf_sja_optional.add_argument('--permit-rfm-create', action='store_true') diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py index 4134650..0614a0c 100644 --- a/pySim/ts_31_102.py +++ b/pySim/ts_31_102.py @@ -39,6 +39,7 @@ from pySim.filesystem import * from pySim.ts_31_102_telecom import DF_PHONEBOOK, EF_UServiceTable from pySim.construct import * +from pySim.utils import is_hexstr from pySim.cat import SMS_TPDU, DeviceIdentities, SMSPPDownload from construct import Optional as COptional from construct import * @@ -1588,8 +1589,8 @@ super().__init__() authenticate_parser = argparse.ArgumentParser() - authenticate_parser.add_argument('rand', help='Random challenge') - authenticate_parser.add_argument('autn', help='Authentication Nonce') + authenticate_parser.add_argument('rand', type=is_hexstr, help='Random challenge') + authenticate_parser.add_argument('autn', type=is_hexstr, help='Authentication Nonce') #authenticate_parser.add_argument('--context', help='Authentication context', default='3G') @cmd2.with_argparser(authenticate_parser) @@ -1599,7 +1600,7 @@ self._cmd.poutput_json(data) term_prof_parser = argparse.ArgumentParser() - term_prof_parser.add_argument('PROFILE', help='Hexstring of encoded terminal profile') + term_prof_parser.add_argument('PROFILE', type=is_hexstr, help='Hexstring of encoded terminal profile') @cmd2.with_argparser(term_prof_parser) def do_terminal_profile(self, opts): @@ -1613,7 +1614,7 @@ self._cmd.poutput('SW: %s, data: %s' % (sw, data)) envelope_parser = argparse.ArgumentParser() - envelope_parser.add_argument('PAYLOAD', help='Hexstring of encoded payload to ENVELOPE') + envelope_parser.add_argument('PAYLOAD', type=is_hexstr, help='Hexstring of encoded payload to ENVELOPE') @cmd2.with_argparser(envelope_parser) def do_envelope(self, opts): @@ -1625,7 +1626,7 @@ self._cmd.poutput('SW: %s, data: %s' % (sw, data)) envelope_sms_parser = argparse.ArgumentParser() - envelope_sms_parser.add_argument('TPDU', help='Hexstring of encoded SMS TPDU') + envelope_sms_parser.add_argument('TPDU', type=is_hexstr, help='Hexstring of encoded SMS TPDU') @cmd2.with_argparser(envelope_sms_parser) def do_envelope_sms(self, opts): diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 0a6f774..9b56b0e 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -1034,7 +1034,7 @@ super().__init__() authenticate_parser = argparse.ArgumentParser() - authenticate_parser.add_argument('rand', help='Random challenge') + authenticate_parser.add_argument('rand', type=is_hexstr, help='Random challenge') @cmd2.with_argparser(authenticate_parser) def do_authenticate(self, opts): -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35551?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: I6426ea864bec82be60554dd125961a48d7751904 Gerrit-Change-Number: 35551 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in pysim[master]: global_platform: Implement generic store_data command
by laforge 12 Jan '24

12 Jan '24
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/35553?usp=email ) Change subject: global_platform: Implement generic store_data command ...................................................................... global_platform: Implement generic store_data command Change-Id: If30c5d31b4e7dd60d3a5cfb1d1cbdcf61741a50e --- M pySim/global_platform.py 1 file changed, 50 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/53/35553/1 diff --git a/pySim/global_platform.py b/pySim/global_platform.py index e04e845..9c375cd 100644 --- a/pySim/global_platform.py +++ b/pySim/global_platform.py @@ -287,6 +287,12 @@ # Application Dedicated File of a Security Domain class ADF_SD(CardADF): + StoreData = BitStruct('last_block'/Flag, + 'encryption'/Enum(BitsInteger(2), none=0, application_dependent=1, rfu=2, encrypted=3), + 'structure'/Enum(BitsInteger(2), none=0, dgi=1, ber_tlv=2, rfu=3), + '_pad'/Padding(2), + 'response'/Enum(Bit, not_expected=0, may_be_returned=1)) + def __init__(self, aid: str, name: str, desc: str): super().__init__(aid=aid, fid=None, sfid=None, name=name, desc=desc) self.shell_commands += [self.AddlShellCommands()] @@ -325,6 +331,41 @@ index_dict = {1: data_dict} return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict) + store_data_parser = argparse.ArgumentParser() + store_data_parser.add_argument('--data-structure', type=str, choices=['none','dgi','ber_tlv','rfu'], default='none') + store_data_parser.add_argument('--encryption', type=str, choices=['none','application_dependent', 'rfu', 'encrypted'], default='none') + store_data_parser.add_argument('--response', type=str, choices=['not_expected','may_be_returned'], default='not_expected') + store_data_parser.add_argument('DATA', type=is_hexstr) + + @cmd2.with_argparser(store_data_parser) + def do_store_data(self, opts): + """Perform the GlobalPlatform GET DATA command in order to store some card-specific data. + See GlobalPlatform CardSpecification v2.3Section 11.11 for details.""" + response_permitted = True if opts.response == 'may_be_returned' else False + self.store_data(h2b(opts.DATA), opts.data_structure, opts.encryption, response_permitted) + + def store_data(self, data: bytes, structure:str = 'none', encryption:str = 'none', response_permitted: bool = False) -> bytes: + """Perform the GlobalPlatform GET DATA command in order to store some card-specific data. + See GlobalPlatform CardSpecification v2.3Section 11.11 for details.""" + # Table 11-89 of GP Card Specification v2.3 + remainder = data + block_nr = 0 + response = '' + while len(remainder): + chunk = remainder[:255] + remainder = remainder[255:] + p1b = build_construct(ADF_SD.StoreData, + {'last_block': len(remainder) == 0, 'encryption': encryption, + 'structure': structure, 'response': response_permitted}) + hdr = "80E2%02x%02x%02x" % (p1b[0], block_nr, len(chunk)) + data, sw = self._cmd.lchan.scc._tp.send_apdu_checksw(hdr + b2h(chunk)) + block_nr += 1 + response += data + return data + + + + # Card Application of a Security Domain class CardApplicationSD(CardApplication): __intermediate = True -- To view, visit https://gerrit.osmocom.org/c/pysim/+/35553?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If30c5d31b4e7dd60d3a5cfb1d1cbdcf61741a50e Gerrit-Change-Number: 35553 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[M] Change in osmo-mgw[master]: Revert "drop (now) unused code"
by neels 11 Jan '24

11 Jan '24
neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-mgw/+/35526?usp=email ) Change subject: Revert "drop (now) unused code" ...................................................................... Revert "drop (now) unused code" This reverts commit 2b30cbdfa83c20045ef92f53e88441dda185591b. Reason for revert: Older versions of osmo-msc were actually calling map_codec_to_pt(). Change-Id: Ifff31012b327d40ed0b1559d5cf4f320784a4061 Related: https://jenkins.osmocom.org/jenkins/job/Osmocom-build-tags-against-master/1… --- M TODO-RELEASE M include/osmocom/mgcp_client/mgcp_client.h M src/libosmo-mgcp-client/mgcp_client.c M tests/mgcp_client/mgcp_client_test.c M tests/mgcp_client/mgcp_client_test.err M tests/mgcp_client/mgcp_client_test.ok 6 files changed, 191 insertions(+), 5 deletions(-) Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified diff --git a/TODO-RELEASE b/TODO-RELEASE index f1a702f..964ffe1 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -38,8 +38,3 @@ libosmo-mgcp-client deprecate public API New code should no longer use codecs[], instead use ptmap[].codec. There is backwards compat code that moves codecs[] entries, if any, over to ptmap[], so callers may migrate at own leisure. -libosmo-mgcp-client remove public API Since codecs[] has been deprecated in favor of ptmap[], there is no use - for the following functions; all known callers have been within - osmo-mgw.git: - map_codec_to_pt() - map_pt_to_codec() diff --git a/include/osmocom/mgcp_client/mgcp_client.h b/include/osmocom/mgcp_client/mgcp_client.h index e1748a6..1d33690 100644 --- a/include/osmocom/mgcp_client/mgcp_client.h +++ b/include/osmocom/mgcp_client/mgcp_client.h @@ -119,5 +119,9 @@ } enum mgcp_codecs map_str_to_codec(const char *str); +unsigned int map_codec_to_pt(const struct ptmap *ptmap, unsigned int ptmap_len, + enum mgcp_codecs codec); +enum mgcp_codecs map_pt_to_codec(struct ptmap *ptmap, unsigned int ptmap_len, + unsigned int pt); const char *mgcp_client_name(const struct mgcp_client *mgcp); diff --git a/src/libosmo-mgcp-client/mgcp_client.c b/src/libosmo-mgcp-client/mgcp_client.c index bfe69e6..489ce69 100644 --- a/src/libosmo-mgcp-client/mgcp_client.c +++ b/src/libosmo-mgcp-client/mgcp_client.c @@ -105,6 +105,94 @@ return -1; } +/* Check the ptmap for illegal mappings */ +static int check_ptmap(const struct ptmap *ptmap) +{ + /* Check if there are mappings that leave the IANA assigned dynamic + * payload type range. Under normal conditions such mappings should + * not occur */ + + /* Its ok to have a 1:1 mapping in the statically defined + * range, this won't hurt */ + if (ptmap->codec == ptmap->pt) + return 0; + + if (ptmap->codec < 96 || ptmap->codec > 127) + goto error; + if (ptmap->pt < 96 || ptmap->pt > 127) + goto error; + + return 0; +error: + LOGP(DLMGCP, LOGL_ERROR, + "ptmap contains illegal mapping: codec=%u maps to pt=%u\n", + ptmap->codec, ptmap->pt); + return -1; +} + +/*! Map a codec to a payload type. + * \ptmap[in] payload pointer to payload type map with specified payload types. + * \ptmap[in] ptmap_len length of the payload type map. + * \ptmap[in] codec the codec for which the payload type should be looked up. + * \returns assigned payload type */ +unsigned int map_codec_to_pt(const struct ptmap *ptmap, unsigned int ptmap_len, + enum mgcp_codecs codec) +{ + unsigned int i; + + /*! Note: If the payload type map is empty or the codec is not found + * in the map, then a 1:1 mapping is performed. If the codec falls + * into the statically defined range or if the mapping table isself + * tries to map to the statically defined range, then the mapping + * is also ignored and a 1:1 mapping is performed instead. */ + + /* we may return the codec directly since enum mgcp_codecs directly + * corresponds to the statically assigned payload types */ + if (codec < 96 || codec > 127) + return codec; + + for (i = 0; i < ptmap_len; i++) { + /* Skip illegal map entries */ + if (check_ptmap(ptmap) == 0 && ptmap->codec == codec) + return ptmap->pt; + ptmap++; + } + + /* If nothing is found, do not perform any mapping */ + return codec; +} + +/*! Map a payload type to a codec. + * \ptmap[in] payload pointer to payload type map with specified payload types. + * \ptmap[in] ptmap_len length of the payload type map. + * \ptmap[in] payload type for which the codec should be looked up. + * \returns codec that corresponds to the specified payload type */ +enum mgcp_codecs map_pt_to_codec(struct ptmap *ptmap, unsigned int ptmap_len, + unsigned int pt) +{ + unsigned int i; + + /*! Note: If the payload type map is empty or the payload type is not + * found in the map, then a 1:1 mapping is performed. If the payload + * type falls into the statically defined range or if the mapping + * table isself tries to map to the statically defined range, then + * the mapping is also ignored and a 1:1 mapping is performed + * instead. */ + + /* See also note in map_codec_to_pt() */ + if (pt < 96 || pt > 127) + return pt; + + for (i = 0; i < ptmap_len; i++) { + if (check_ptmap(ptmap) == 0 && ptmap->pt == pt) + return ptmap->codec; + ptmap++; + } + + /* If nothing is found, do not perform any mapping */ + return pt; +} + static void _mgcp_client_conf_init(struct mgcp_client_conf *conf) { /* NULL and -1 default to MGCP_CLIENT_*_DEFAULT values */ diff --git a/tests/mgcp_client/mgcp_client_test.c b/tests/mgcp_client/mgcp_client_test.c index 95a742f..9b356c3 100644 --- a/tests/mgcp_client/mgcp_client_test.c +++ b/tests/mgcp_client/mgcp_client_test.c @@ -571,6 +571,57 @@ OSMO_ASSERT(map_str_to_codec("AMR-WB####################################################################################################################") == -1); } +static void test_map_codec_to_pt_and_map_pt_to_codec(void) +{ + struct ptmap ptmap[10]; + unsigned int ptmap_len; + unsigned int i; + + ptmap[0].codec = CODEC_GSMEFR_8000_1; + ptmap[0].pt = 96; + ptmap[1].codec = CODEC_GSMHR_8000_1; + ptmap[1].pt = 97; + ptmap[2].codec = CODEC_AMR_8000_1; + ptmap[2].pt = 98; + ptmap[3].codec = CODEC_AMRWB_16000_1; + ptmap[3].pt = 99; + ptmap_len = 4; + + /* Mappings that are covered by the table */ + for (i = 0; i < ptmap_len; i++) + printf(" %u => %u\n", ptmap[i].codec, map_codec_to_pt(ptmap, ptmap_len, ptmap[i].codec)); + for (i = 0; i < ptmap_len; i++) + printf(" %u <= %u\n", ptmap[i].pt, map_pt_to_codec(ptmap, ptmap_len, ptmap[i].pt)); + printf("\n"); + + /* Map some codecs/payload types from the static range, result must + * always be a 1:1 mapping */ + printf(" %u => %u\n", CODEC_PCMU_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_PCMU_8000_1)); + printf(" %u => %u\n", CODEC_GSM_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_GSM_8000_1)); + printf(" %u => %u\n", CODEC_PCMA_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_PCMA_8000_1)); + printf(" %u => %u\n", CODEC_G729_8000_1, map_codec_to_pt(ptmap, ptmap_len, CODEC_G729_8000_1)); + printf(" %u <= %u\n", CODEC_PCMU_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_PCMU_8000_1)); + printf(" %u <= %u\n", CODEC_GSM_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_GSM_8000_1)); + printf(" %u <= %u\n", CODEC_PCMA_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_PCMA_8000_1)); + printf(" %u <= %u\n", CODEC_G729_8000_1, map_pt_to_codec(ptmap, ptmap_len, CODEC_G729_8000_1)); + printf("\n"); + + /* Try to do mappings from statically defined range to danymic range and vice versa. This + * is illegal and should result into a 1:1 mapping */ + ptmap[3].codec = CODEC_AMRWB_16000_1; + ptmap[3].pt = 2; + ptmap[4].codec = CODEC_PCMU_8000_1; + ptmap[4].pt = 100; + ptmap_len = 5; + + /* Apply all mappings again, the illegal ones we defined should result into 1:1 mappings */ + for (i = 0; i < ptmap_len; i++) + printf(" %u => %u\n", ptmap[i].codec, map_codec_to_pt(ptmap, ptmap_len, ptmap[i].codec)); + for (i = 0; i < ptmap_len; i++) + printf(" %u <= %u\n", ptmap[i].pt, map_pt_to_codec(ptmap, ptmap_len, ptmap[i].pt)); + printf("\n"); +} + void test_mgcp_client_e1_epname(void) { char *epname; @@ -857,6 +908,7 @@ test_mgcp_msg(); test_mgcp_client_cancel(); test_sdp_section_start(); + test_map_codec_to_pt_and_map_pt_to_codec(); test_map_str_to_codec(); test_mgcp_client_e1_epname(); diff --git a/tests/mgcp_client/mgcp_client_test.err b/tests/mgcp_client/mgcp_client_test.err index 9e98792..94fe351 100644 --- a/tests/mgcp_client/mgcp_client_test.err +++ b/tests/mgcp_client/mgcp_client_test.err @@ -128,6 +128,10 @@ body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 \r\n" DLMGCP Failed to parse MGCP response header (audio ip) got rc=-22 +DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2 +DLMGCP ptmap contains illegal mapping: codec=0 maps to pt=100 +DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2 +DLMGCP ptmap contains illegal mapping: codec=0 maps to pt=100 DLMGCP MGW(mgw) MGCP client: using endpoint domain '@mgw' DLMGCP MGW(mgw) Cannot compose MGCP e1-endpoint name (ds/e1-15/s-1/su128-0@mgw), rate(128)/offset(0) combination is invalid! DLMGCP MGW(mgw) Cannot compose MGCP e1-endpoint name (ds/e1-15/s-1/su8-16@mgw), rate(8)/offset(16) combination is invalid! diff --git a/tests/mgcp_client/mgcp_client_test.ok b/tests/mgcp_client/mgcp_client_test.ok index b16d1bc..039fbd9 100644 --- a/tests/mgcp_client/mgcp_client_test.ok +++ b/tests/mgcp_client/mgcp_client_test.ok @@ -181,6 +181,35 @@ test_sdp_section_start() test [17]: test_sdp_section_start() test [18]: + 110 => 96 + 111 => 97 + 112 => 98 + 113 => 99 + 96 <= 110 + 97 <= 111 + 98 <= 112 + 99 <= 113 + + 0 => 0 + 3 => 3 + 8 => 8 + 18 => 18 + 0 <= 0 + 3 <= 3 + 8 <= 8 + 18 <= 18 + + 110 => 96 + 111 => 97 + 112 => 98 + 113 => 113 + 0 => 0 + 96 <= 110 + 97 <= 111 + 98 <= 112 + 2 <= 2 + 100 <= 100 + ds/e1-1/s-15/su64-0@mgw ds/e1-2/s-14/su32-0@mgw ds/e1-3/s-13/su32-4@mgw -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/35526?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: Ifff31012b327d40ed0b1559d5cf4f320784a4061 Gerrit-Change-Number: 35526 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-mgw[master]: Revert "drop (now) unused code"
by laforge 11 Jan '24

11 Jan '24
Attention is currently required from: neels, pespin. laforge has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-mgw/+/35526?usp=email ) Change subject: Revert "drop (now) unused code" ...................................................................... Patch Set 1: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/35526?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: Ifff31012b327d40ed0b1559d5cf4f320784a4061 Gerrit-Change-Number: 35526 Gerrit-PatchSet: 1 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Thu, 11 Jan 2024 19:45:54 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-mgw[master]: drop (now) unused code
by neels 11 Jan '24

11 Jan '24
neels has created a revert of this change. ( https://gerrit.osmocom.org/c/osmo-mgw/+/35247?usp=email ) Change subject: drop (now) unused code ...................................................................... -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/35247?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: I84e5285831397c992af59deee12dea8458d16cc6 Gerrit-Change-Number: 35247 Gerrit-PatchSet: 6 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: revert
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • ...
  • 156
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.