Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43556?usp=email )
Change subject: sms: don't mutate digits in AddressField.to_bytes()
......................................................................
sms: don't mutate digits in AddressField.to_bytes()
to_bytes() appended the BCD filler nibble, so the next call saw one
digit more and derived a wrong length. This affects any code that encodes
an address twice, even for printing/logging.
Man, I really miss my beloved c++ const function decoration...
Fix: keep the filler in a local.
Change-Id: I81691c5a1fc5072d6d20c52d22da1eb2e180d04a
---
M pySim/sms.py
1 file changed, 3 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/56/43556/1
diff --git a/pySim/sms.py b/pySim/sms.py
index 0c73a53..5d2bda9 100644
--- a/pySim/sms.py
+++ b/pySim/sms.py
@@ -239,8 +239,8 @@
def to_bytes(self) -> bytes:
"""Encode the AddressField into the binary representation as used in T-PDU."""
num_digits = len(self.digits)
- if num_digits % 2:
- self.digits += 'f'
+ # don't store the filler nibble or get_bytes() encodes it as digit and ends up too large
+ digits = self.digits + 'f' if num_digits % 2 else self.digits
d = {
'addr_len': num_digits,
'type_of_addr': {
@@ -248,7 +248,7 @@
'type_of_number': self.ton,
'numbering_plan_id': self.npi,
},
- 'digits': self.digits,
+ 'digits': digits,
}
return self._construct.build(d)
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43556?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I81691c5a1fc5072d6d20c52d22da1eb2e180d04a
Gerrit-Change-Number: 43556
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43555?usp=email )
Change subject: tools: print tracebacks to the same stream as delimiters
......................................................................
tools: print tracebacks to the same stream as delimiters
Error output is currently a garbled mess, delimiters are printed with
poutput() or print(), traceback with traceback.print_exc() which goes
to stderr.
Reading stdout alone omits the report but not -->8-- lines.
Reading both streams makes the traceback appear where the two buffers
just happen to interleave, stderr is usually unbuffered but stdout is
not, so I get the error trace, APDU trace, then empty -->8-- lines.
Fix this by aligning the printing funcs.
Change-Id: I2ed37dfe241d014e4a26894cddbc9b21be1fd0c2
---
M pySim-prog.py
M pySim-shell.py
2 files changed, 4 insertions(+), 4 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/55/43555/1
diff --git a/pySim-prog.py b/pySim-prog.py
index 6111fc1..0a3e888 100755
--- a/pySim-prog.py
+++ b/pySim-prog.py
@@ -816,7 +816,7 @@
print("")
print("Card programming failed with an exception:")
print("---------------------8<---------------------")
- traceback.print_exc()
+ print(traceback.format_exc().rstrip())
print("---------------------8<---------------------")
print("")
rc = -1
diff --git a/pySim-shell.py b/pySim-shell.py
index 31de001..4552bd0 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -351,7 +351,7 @@
self.poutput("")
self.poutput("Card initialization (%s) failed with an exception:" % str(self.sl))
self.poutput("---------------------8<---------------------")
- traceback.print_exc()
+ self.poutput(traceback.format_exc().rstrip())
self.poutput("---------------------8<---------------------")
self.poutput("")
return -1
@@ -465,7 +465,7 @@
self.poutput("")
self.poutput("Card handling (%s) failed with an exception:" % str(self.sl))
self.poutput("---------------------8<---------------------")
- traceback.print_exc()
+ self.poutput(traceback.format_exc().rstrip())
self.poutput("---------------------8<---------------------")
self.poutput("")
fail_count = fail_count + 1
@@ -1173,7 +1173,7 @@
startup_errors = True
print("Card initialization (%s) failed with an exception:" % str(sl))
print("---------------------8<---------------------")
- traceback.print_exc()
+ print(traceback.format_exc().rstrip())
print("---------------------8<---------------------")
if not opts.noprompt:
print("(you may still try to recover from this manually by using the 'equip' command.)")
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43555?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I2ed37dfe241d014e4a26894cddbc9b21be1fd0c2
Gerrit-Change-Number: 43555
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43557?usp=email )
Change subject: cat: add sms_pp_download_envelope()
......................................................................
cat: add sms_pp_download_envelope()
Put a helper for wrapping an SMS-DELIVER TPDU in the ENVELOPE
of TS 102 223 section 7.5.1 the assembly next to SMSPPDownload,
where the IEs already live, so it can be reused by other tooling,
for example for triggering scp81 sessions.
Change-Id: Id23227eac53d697f4f13a84e087c32bf1d60f474
---
M pySim-smpp2sim.py
M pySim/cat.py
2 files changed, 18 insertions(+), 4 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/57/43557/1
diff --git a/pySim-smpp2sim.py b/pySim-smpp2sim.py
index f7a45f5..95b9ccd 100755
--- a/pySim-smpp2sim.py
+++ b/pySim-smpp2sim.py
@@ -55,6 +55,7 @@
from pySim.commands import SimCardCommands
from pySim.cards import UiccCardBase
from pySim.exceptions import *
+from pySim.cat import sms_pp_download_envelope
from pySim.cat import ProactiveCommand, SendShortMessage, SMS_TPDU, SMSPPDownload, BearerDescription
from pySim.cat import DeviceIdentities, Address, OtherAddress, UiccTransportLevel, BufferSize
from pySim.cat import ChannelStatus, ChannelData, ChannelDataLength
@@ -169,10 +170,7 @@
tpdu = SMS_DELIVER.from_smpp_submit(pdu)
logger.info(tpdu)
# 2) wrap into the CAT ENVELOPE for SMS-PP-Download
- tpdu_ie = SMS_TPDU(decoded={'tpdu': b2h(tpdu.to_bytes())})
- addr_ie = Address(decoded={'ton_npi': {'ext':False, 'type_of_number':'unknown', 'numbering_plan_id':'unknown'}, 'call_number': '0123456'})
- dev_ids = DeviceIdentities(decoded={'source_dev_id': 'network', 'dest_dev_id': 'uicc'})
- sms_dl = SMSPPDownload(children=[dev_ids, addr_ie, tpdu_ie])
+ sms_dl = sms_pp_download_envelope(tpdu)
# 3) send to the card
envelope_hex = b2h(sms_dl.to_tlv())
logger.info("ENVELOPE: %s" % envelope_hex)
diff --git a/pySim/cat.py b/pySim/cat.py
index d755545..8959004 100644
--- a/pySim/cat.py
+++ b/pySim/cat.py
@@ -763,6 +763,22 @@
nested=[DeviceIdentities, Address, SMS_TPDU]):
pass
+
+def sms_pp_download_envelope(tpdu, call_number: str = '0123456') -> SMSPPDownload:
+ """TS 31.111 Section 7.1.1.2 wrap of a SMS-DELIVER TPDU in the ENVELOPE (SMS-PP Download)
+ call_number :
+ SMSC address to report, defined in TS 31.111 7.1.1.2 as
+ "the RP_Originating_Address of the Service Centre (TS-Service-Centre-Address, 3GPP TS 24.011)"
+ its presence is Conditional, and the note there says the UICC should be fine
+ if its missing, so for remote management its presence should suffice (?).
+ """
+ return SMSPPDownload(children=[
+ DeviceIdentities(decoded={'source_dev_id': 'network', 'dest_dev_id': 'uicc'}),
+ Address(decoded={'ton_npi': {'ext': False, 'type_of_number': 'unknown',
+ 'numbering_plan_id': 'unknown'},
+ 'call_number': call_number}),
+ SMS_TPDU(decoded={'tpdu': b2h(tpdu.to_bytes())})])
+
# TS 101 220 Table 7.17 + 31.111 7.1.1.3
class SMSCBDownload(BER_TLV_IE, tag=0xD2,
nested=[DeviceIdentities, CBSPage]):
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43557?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Id23227eac53d697f4f13a84e087c32bf1d60f474
Gerrit-Change-Number: 43557
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43559?usp=email )
Change subject: cat: fix Supported Radio Access Technologies state flag
......................................................................
cat: fix Supported Radio Access Technologies state flag
TS 102 223 8.105 codes each supported technology in two bytes:
- the technology from 8.61
- state byte, b1 0 disabled/1 enabled
- b2-b8 RFU
Currently declared as FlagsEnum(Int8ub, enabled=0). kw value is used as
bitmask, so currently:
build {'enabled': True} -> b4 02 08 00 disabled
build {'enabled': False} -> b4 02 08 00 disabled
but parsed 08 00 / 08 01 / 08 ff -> all {'enabled': True}
Use the bit the spec names + tests because well this is so easy that we
don't need tests is apparently not the right approach here..
Change-Id: I4dd16182eb06c99265aabab5d889967b890f6bf2
---
M pySim/cat.py
A tests/unittests/test_cat.py
2 files changed, 67 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/59/43559/1
diff --git a/pySim/cat.py b/pySim/cat.py
index 8959004..2fda7c5 100644
--- a/pySim/cat.py
+++ b/pySim/cat.py
@@ -729,8 +729,12 @@
# TS 102 223 Section 8.105
class SupportedRadioAccessTechnologies(COMPR_TLV_IE, tag=0xB4):
+ # 2 bytes/entry:
+ # - technology of 8.61
+ # - state byte b1 is 0 disabled/1 enabled
+ # - b2-b8 RFU.
AccessTechTuple = Struct('technology'/AccessTechnology.SingleAccessTech,
- 'state'/FlagsEnum(Int8ub, enabled=0))
+ 'state'/FlagsEnum(Int8ub, enabled=1))
_construct = GreedyRange(AccessTechTuple)
# TS 102 223 Section 8.107
diff --git a/tests/unittests/test_cat.py b/tests/unittests/test_cat.py
new file mode 100644
index 0000000..4e0450c
--- /dev/null
+++ b/tests/unittests/test_cat.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+"""Tests for the CAT (Card Application Toolkit) COMPREHENSION-TLV data objects"""
+
+# (C) 2026 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+#
+# Author: Eric Wild
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# IEs not properly coverd by test_tlvs.py
+
+
+import unittest
+
+from osmocom.utils import b2h, h2b
+
+from pySim.cat import SupportedRadioAccessTechnologies
+
+
+class SupportedRadioAccessTechnologies_Test(unittest.TestCase):
+ """TS 102 223 8.105"""
+
+ def test_enabled_is_encodable(self):
+ """The flag used to have a bm of 0 so enabled -> 00 (that is disabled..)"""
+ ie = SupportedRadioAccessTechnologies(
+ decoded=[{'technology': 'eutran', 'state': {'enabled': True}}])
+ self.assertEqual(b2h(ie.to_tlv()), 'b4020801')
+
+ def test_disabled_differs_from_enabled(self):
+ ie = SupportedRadioAccessTechnologies(
+ decoded=[{'technology': 'eutran', 'state': {'enabled': False}}])
+ self.assertEqual(b2h(ie.to_tlv()), 'b4020800')
+
+ def test_state_byte_is_read_back_faithfully(self):
+ """old 0 bm = all enabled, no way to disable"""
+ for encoded, enabled in [('b4020800', False), ('b4020801', True)]:
+ with self.subTest(encoded=encoded):
+ ie = SupportedRadioAccessTechnologies()
+ ie.from_tlv(h2b(encoded))
+ self.assertEqual(ie.decoded[0]['state']['enabled'], enabled)
+
+ def test_multiple_technologies(self):
+ ie = SupportedRadioAccessTechnologies()
+ ie.from_tlv(h2b('b40408010000'))
+ self.assertEqual([(e['technology'], e['state']['enabled']) for e in ie.decoded],
+ [('eutran', True), ('gsm', False)])
+
+
+
+if __name__ == "__main__":
+ unittest.main()
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43559?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I4dd16182eb06c99265aabab5d889967b890f6bf2
Gerrit-Change-Number: 43559
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43558?usp=email )
Change subject: bip: answer proactive commands the relay does not implement
......................................................................
bip: answer proactive commands the relay does not implement
pySim-smpp2sim currently claims to support every feature flag that exists,
but this immediately dies here with a SJA5:
NotImplementedError: No handler method for ProvideLocalInformation(...)
Answer anything unhandled with "performed_successfully" and log. Never
"command_beyond_terminal_capability", tho, answering that for PROVIDE LOCAL
INFORMATION refuses to open the session at all.
Change-Id: I1e55d6f88c872a04b89a3946dd840d30b329621e
---
M pySim/bip.py
1 file changed, 19 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/58/43558/1
diff --git a/pySim/bip.py b/pySim/bip.py
index e5ec029..14c75bc 100644
--- a/pySim/bip.py
+++ b/pySim/bip.py
@@ -203,6 +203,25 @@
self.sms_sink = sms_sink
self.channels = ProactChannels(on_data_available=self._on_channel_data_available)
+ def receive_fetch(self, pcmd: ProactiveCommand):
+ """Answer anything this handler has no specific handler for.
+
+ A card coming up will usually issue PROVIDE LOCAL INFORMATION,
+ POLL INTERVAL or TIMER MANAGEMENT before it gets anywhere near a BIP channel
+ because we claim to support every feature flag there is.
+
+ Note that this is not the spec-correct answer. TS 102 223 6.8.7
+ says a successful TERMINAL RESPONSE to PROVIDE LOCAL INFORMATION "shall" carry the
+ requested Local information data object, and 6.8.13/6.8.14 says the same for TIMER
+ MANAGEMENT, this returns empty results for all of them, which works with real cards.
+
+ Always "performed_successfully", never "command_beyond_terminal_capability" because
+ answering that to PROVIDE LOCAL INFORMATION makes a card refuse to open the session.
+ """
+ logger.info("no handler for %s, answering performed_successfully",
+ type(pcmd.decoded).__name__)
+ return self.prepare_response(pcmd, 'performed_successfully')
+
@staticmethod
def _find_first_element_of_type(instlist, cls):
for i in instlist:
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43558?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I1e55d6f88c872a04b89a3946dd840d30b329621e
Gerrit-Change-Number: 43558
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43562?usp=email )
Change subject: osmo-smdpp: case insensitive comp of ES9+ SM-DP+ address
......................................................................
osmo-smdpp: case insensitive comp of ES9+ SM-DP+ address
Do what the comment above the line already says..
Change-Id: Ie0738e810572ea3312c885ec8aaa2da4b8b12cd7
---
M osmo-smdpp.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/62/43562/1
diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index ef214a9..5ac08df 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -525,7 +525,7 @@
"""See ES9+ InitiateAuthentication SGP.22 Section 5.6.1"""
# Verify that the received address matches its own SM-DP+ address, where the comparison SHALL be
# case-insensitive. Otherwise, the SM-DP+ SHALL return a status code "SM-DP+ Address - Refused".
- if content['smdpAddress'] != self.server_hostname:
+ if content['smdpAddress'].lower() != self.server_hostname.lower():
raise ApiError('8.8.1', '3.8', 'Invalid SM-DP+ Address')
euiccChallenge = b64decode(content['euiccChallenge'])
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43562?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ie0738e810572ea3312c885ec8aaa2da4b8b12cd7
Gerrit-Change-Number: 43562
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>