Skip to content

Loading builds...

Changes

#29008 (Jul 10, 2026, 3:36:25 PM)

esipa_asn1_handler: use eimTransactionId in EimPackageResultResponseError

EimPackageResultResponseError contains an eimTransactionId, let's use this
eimTransactionId and add a dedicated handler function for the
EimPackageResultResponseError to esipa_asn1_handler_utils

Change-Id: Iadd852a7531f180618cf12b314170ceea3f97615
Related: SYS#8100
pmaier@sysmocom.de at

#29007 (Jul 10, 2026, 3:36:22 PM)

mnesia_db_rest: add comment on why we create an euicc entry early

Even though it is technically not necessary, we ensure that an
entry is present in the euicc table on each REST API call. Let's
add a comment to explain why we do it anyway.

Change-Id: Ifb9340655c5f36e074a1a92c0e234ef62c79b9d8
pmaier@sysmocom.de at

#29006 (Jul 10, 2026, 3:36:19 PM)

mnesia_db_euicc: renovate handling of euicc table (mnesia, REST)

The REST API that allows users to set certain eUICC parameters
(we call them "states" from now on) only allows to set eUICC
states, but doesn't allow to read them back.

With this patch, we renovate the handling of the mnesia euicc
table from the ground up so that REST API users have read and
write access to the states stored in the mnesia euicc table.

Related: SYS#8100

The original purpose of the euicc table was to hold static params
for an eUICC (e.g. the public key or the flag that tells if it is
a consumer eUICC or not). Now that we plan to extend the scope
of the euicc table, it makes more sense to talk about states rather
than parameters.

Change-Id: I74c602555b194a28d6eb9dd67ec4c6a8865fcb77
pmaier@sysmocom.de at

#29005 (Jul 10, 2026, 3:36:16 PM)

doc/build.md: fix typo

Related: SYS#8100
Change-Id: Ie6a066f3289fbdde40f55bd9f38a3dd90102e7e6
pmaier@sysmocom.de at

#29004 (Jul 10, 2026, 3:36:13 PM)

contrib/tryme_euiccDataRequest: fixup example tag string

The eUICC data request takes a string with TLV tags as input. The
example in this example still uses tags from SGP.32 V.1.0.1, let's
update the string so that it is compliant with SGP.32 V.1.2.

(see also SGP.32, section 2.11.1.2)

Related: SYS:8100
Change-Id: I5be04c954330638d3e7d78e8f5f280bebb707efa
pmaier@sysmocom.de at

#29003 (Jul 10, 2026, 3:36:10 PM)

mnesia_db_euicc: rename timer_setparam to timer_rest

The function timer_setparam is processing REST API orders
in regular intervals. Naming the timer "timer_rest" makes
more sense.

Change-Id: Icfa203477e044ce2cc312d4b6e2693a97191c61d
pmaier@sysmocom.de at

#29002 (Jul 10, 2026, 3:36:07 PM)

esipa: rename TransactionId to EimTransactionId where applicable

In SGP.32 V.1.2 all TransactionIds which are generated by the eIM are
called now called "eimTransactionId". Let's make sure that we name
the EimTransactionId variables and atoms (eimTransactionId) accordingly.

Change-Id: Ia97f96c27d5dc4405effd5266de4cdb797849699
Related: SYS#8100
pmaier@sysmocom.de at

#29001 (Jul 10, 2026, 3:36:04 PM)

esipa_asn1_handler: replace handle_asn1_notificationList

The helper function handle_asn1_notificationList can also be
described using the comprehension syntax.

Change-Id: Ia95f56998b4f7a8b0f9fce727d82dedc942e5aeb
Related: SYS#8100
pmaier@sysmocom.de at

#29000 (Jul 10, 2026, 3:36:01 PM)

esipa_asn1_handler_utils: use maps:find

We can replace maps:is_key and maps:get with a single maps:find call.

Change-Id: I6cc151deef161f3ca4726e6b81ae1f5cc80ad184
Related: SYS#8100
pmaier@sysmocom.de at

#28999 (Jul 10, 2026, 3:35:57 PM)

esipa_asn1_handler: use eimTransactionId for ipaEuiccDataResponse

The ipaEuiccDataResponse does currently not use the eimTransactionId,
which was added with SGP.32 V.1.2, let's make use of the eimTransactionId
and move the handler functionality to a dedicated helper function in
esipa_asn_handler_utils.

Change-Id: Ie414eef7fd5c8928dd611503f4dd8d67322c0e80
Related: SYS#8100
pmaier@sysmocom.de at

#28998 (Jul 10, 2026, 3:35:55 PM)

mnesia_db: split functionality into dedicated modules

The mnesia_db module is responsible to handle three different tables
with different scope. Let's split the functionality into separate
modules to make the code easier to maintain.

Change-Id: Ifc649337ab7ce7eb9dc602a1439293130f002f41
Related: SYS#8100
pmaier@sysmocom.de at

#28997 (Jul 10, 2026, 3:35:17 PM)

esipa_asn1_handler_utils: rename EsipaReq to Debuginfo

The parameter EsipaReq only exists because we pass it as
Debuginfo to mnesia_db_work:finish. Let's rename it to
"Debuginfo" in esipa_asn1_handler_utils as well to make
clear what the purpose of this parameter is.

Change-Id: I8115d382172989b9ef7ae7f97ce39520e3e2dd16
Related: SYS#8100
pmaier@sysmocom.de at

#28996 (Jul 10, 2026, 3:35:14 PM)

esipa: supply eimTransactionId in profileDownloadTriggerRequest

When we supply an eimTransactionId in profileDownloadTriggerRequest,
the IPAd will echo the same eimTransactionId in the
initiateAuthenticationRequestEsipa message. This allows the eIM
to distinguish to which transaction (work) the received
initiateAuthenticationRequestEsipa belongs. This was not possible
before. The eIM had to rely soly on the PID of the sub process
which is handling the HTTP connection.

Change-Id: I822d6b2bb51498713739671804b173260e9a28a3
Related: SYS#8100
pmaier@sysmocom.de at

#28995 (Jul 10, 2026, 12:56:49 PM)

IPAd: Make tests work with testenv and current master of IPAd

The IPAd can now be tested using testenv.

Several minor changes are required to run them successfully. All tests
pass now.

Related: SYS#8101
Change-Id: Id4abf15feb179b17594bd11c6e7089469684900c
Andreas Eversberg at

#28994 (Jul 10, 2026, 12:56:37 PM)

Add empty getEimPackageResponse send template

This template can be sent, if no eIM package is available for the IPAd.
The IPAd will then stop polling for new eIM packages terminate (or
delay).

Related: SYS#8101
Change-Id: Idf777e168c2f86ed80ce184cbb65fe86cdabe56a
Andreas Eversberg at

#28993 (Jul 10, 2026, 12:56:33 PM)

IPAd: Add TERMINAL CAPABILITIES request (IoT Device Capabilites)

In order to activate IoT functions on eUICC, IPAd will send a TERMINAL
CAPABILITIES request. This has to be answered by the test-suite.

Related: SYS#8101
Change-Id: I0a6d8d6bb6eb0ee30e14afdb5e4ce37af0ae711e
Andreas Eversberg at

#28992 (Jul 10, 2026, 12:56:26 PM)

eIM: Make tests work with testenv

The eIM can now be tested using testenv.py.

Related: SYS#8100
Change-Id: I38364e4bd5625b301c32fd58b50e35667c64b1be
Andreas Eversberg at

#28991 (Jul 10, 2026, 12:56:19 PM)

IPAd: Update nvstate.bin to SGP.32 Version 1.2

Related: SYS#8101
Change-Id: I3d22980f5f8be546f0d80423b3bd80d197aa8872
Andreas Eversberg at

#28990 (Jul 10, 2026, 12:56:12 PM)

Add close function to HTTP_Server_Emulation

If we want to simulate a broken HTTP request towards the client, we may
wait until the client times out. This results in closing the TCP
connection by the client. It then results in failure of the SSL
connection at Titan's Abstract_Socket component. The TTCN3-tests fails.

One solution is to actively close the connection via a close function.
The client will not wait for the timeout. The Abstact_Socket will then
not receive any failure. The test runs faster.

Related: SYS#8101
Change-Id: Id09976800c7498a7173b5d8911fe545504cfa266
Andreas Eversberg at

#28989 (Jul 10, 2026, 12:04:49 PM)

CMakeLists: add install target for ipa

Change-Id: I1b3d248ca2df14835c65139df90ccd2e2f1b80aa
Oliver Smith at

#28988 (Jul 10, 2026, 12:03:01 PM)

Add 'onomondo-ipa' project

Related: SYS#8100
Change-Id: I732e63625943b20989001102c7447d0e0a62af5a
Oliver Smith at

#28987 (Jul 10, 2026, 10:49:23 AM)

Add 'onomono-eim' project

Related: SYS#8100
Change-Id: I47bfc02397b6f97ad891fe4816763ba634df7934
Andreas Eversberg at

#28986 (Jul 10, 2026, 10:31:53 AM)

Add Makefile and start script for installation

The Makefile allows to compile and install onomondo-eim. This allows to
build it with osmo-dev and therefore build and run it with testenv of
osmo-ttcn3-hacks.

The start script allows to run onomondo-eim without starting erlang by
hand. It was taken from osmo-s1gw repository and log-level option was
added.

The program name changed from 'onomondo_eim_release' to 'onomodo-eim'.

Related: SYS#8100
Change-Id: I4f038c0901c23cbe18ef62eb546e264d0b924cc7
Andreas Eversberg at

#28985 (Jul 10, 2026, 9:22:40 AM)

Support building onomondo-eim

The onomondo-eim project is an erlang project, but it does not have a
Makefile like the others. Run rebar3 directly in that case.

I've also considered always doing this instead of running the Makefile,
but that would break osmo-s1gw, which needs to run "rebar3 asn compile"
before "rebar3 compile" as its Makefile does it.

Change-Id: I551e0b88110ed20fdbc301035fc3dac6e0d83635
Oliver Smith at

#28984 (Jul 10, 2026, 6:34:09 AM)

manuals: ignore osmo-s1gw 0.4.1

Change-Id: Id5bddb61c7ae711242060d31a806bc44fee46e5d
Oliver Smith at

#28983 (Jul 9, 2026, 1:11:46 PM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#28982 (Jul 9, 2026, 12:54:05 PM)

IPAd: Update nvstate.bin to SGP.32 Version 1.2

Related: SYS#8101
Change-Id: I3d22980f5f8be546f0d80423b3bd80d197aa8872
Andreas Eversberg at

#28981 (Jul 9, 2026, 12:54:00 PM)

IPAd: Add TERMINAL CAPABILITIES request (IoT Device Capabilites)

In order to activate IoT functions on eUICC, IPAd will send a TERMINAL
CAPABILITIES request. This has to be answered by the test-suite.

Related: SYS#8101
Change-Id: I0a6d8d6bb6eb0ee30e14afdb5e4ce37af0ae711e
Andreas Eversberg at

#28980 (Jul 9, 2026, 12:50:38 PM)

IPAd: Update nvstate.bin to SGP.32 Version 1.2

Related: SYS#8101
Change-Id: I3d22980f5f8be546f0d80423b3bd80d197aa8872
Andreas Eversberg at

#28979 (Jul 9, 2026, 12:50:34 PM)

IPAd: Add TERMINAL CAPABILITIES request (IoT Device Capabilites)

In order to activate IoT functions on eUICC, IPAd will send a TERMINAL
CAPABILITIES request. This has to be answered by the testsuite.

Related: SYS#8101
Change-Id: I0a6d8d6bb6eb0ee30e14afdb5e4ce37af0ae711e
Andreas Eversberg at

#28978 (Jul 9, 2026, 12:50:30 PM)

eIM: Make tests work with testenv

The eIM can now be tested using testenv.py.

Related: SYS#8100
Change-Id: I38364e4bd5625b301c32fd58b50e35667c64b1be
Andreas Eversberg at

#28977 (Jul 9, 2026, 12:50:11 PM)

IPAd: Make tests work with testenv and current master of IPAd

The IPAd can now be tested using testenv.

Several minor changes are required to run them successfully. All tests
pass now.

Related: SYS#8101
Change-Id: Id4abf15feb179b17594bd11c6e7089469684900c
Andreas Eversberg at

#28976 (Jul 9, 2026, 12:49:29 PM)

Add close function to HTTP_Server_Emulation

If we want to simulate a broken HTTP request towards the client, we may
wait until the client times out. This results in closing the TCP
connection by the client. It then results in failure of the SSL
connection at Titan's Abstract_Socket component. The TTCN3-tests fails.

One solution is to actively close the connection via a close function.
The client will not wait for the timout. The Abstact_Socket will then
not receive any failure. The test runs faster.

Related: SYS#8101
Change-Id: Id09976800c7498a7173b5d8911fe545504cfa266
Andreas Eversberg at

#28975 (Jul 9, 2026, 12:49:23 PM)

Add empty getEimPackageResponse send template

This template can be sent, if no eIM package is available for the IPAd.
The IPAd will then stop polling for new eIM packages terminate (or
delay).

Related: SYS#8101
Change-Id: Idf777e168c2f86ed80ce184cbb65fe86cdabe56a
Andreas Eversberg at

#28974 (Jul 9, 2026, 12:36:43 PM)

redmine: hide avatars

We aren't using gravatar or other 3rd party avatar services, and we
don't want the default avatars either as they can give the same color to
different users, making them look like the same user on first glance.

Related: SYS#8097#note-15
Change-Id: I136549e00f806a76704b354498083002fddb5b67
Oliver Smith at

#28973 (Jul 9, 2026, 11:54:55 AM)

rebar.config: use a fork of rebar3_diameter_compiler

This fixes building on Erlang/OTP 29.  A pull request [1] has been
submitted upstream.  Once merged, we get switch back to upstream.

[1] https://github.com/carlosedp/rebar3_diameter_compiler/pull/28

Change-Id: I548a3fef6f8a23a548fb6376076b9d4a9345d692
Vadim Yanitskiy at

#28972 (Jul 9, 2026, 9:45:49 AM)

contrib/obs-mirror: log to systemd journal

Instead of having a lot of logfiles in /home/pkgmirror and starting the
obs-mirror scripts via cronjob, add systemd services and timers and let
them log to the systemd journal.

Change-Id: I3a567770ef6d98bb3fdc2d52214cacbfe59640ad
Oliver Smith at

#28971 (Jul 9, 2026, 9:44:34 AM)

contrib/obs-mirror: log to systemd journal

Instead of having a lot of logfiles in /home/pkgmirror and starting the
obs-mirror scripts via cronjob, add systemd services and timers and let
them log to the systemd journal.

Change-Id: I3a567770ef6d98bb3fdc2d52214cacbfe59640ad
Oliver Smith at

#28970 (Jul 9, 2026, 8:38:10 AM)

eIM: echo eimTransactionId from euiccDataReq in provideEimPackageResult

The udted eIM now includes an eimTransactionId in its ipaEuiccDataRequest
message, which means that the IPAd (testsuite) has to echo that exact
same eimTransactionId in the IpaEuiccData of the IpaEuiccDataResponse

Related: SYS#8100
Change-Id: I286362e6499eb9440e006f08b7c142c6dfd98843
pmaier@sysmocom.de at

#28969 (Jul 9, 2026, 8:38:06 AM)

eIM, REST: use template to encode eimConfigurationData

We currently use a hardcoded binary blob for the testcases that test the
addEim and updateEim eCOs. Let's use the enc_EimConfigurationData encoder
function, which we already have, to encode the eimConfigurationData
instead.

Related: SYS#8100
Change-Id: Ic51731da355cd9a209837d4015c02943367ed90b
pmaier@sysmocom.de at

#28968 (Jul 9, 2026, 8:38:02 AM)

eIM, add new PSMOs introduced with SGP.32 V.1.2

SGP.32 V.1.2 adds new PSMOs, which are setFallbackAttribute,
unsetFallbackAttribute and setDefaultDpAddress. Let's add testcases
for those.

Related: SYS#8100
Change-Id: Ic2416dc06d917228b71c61da9acebed26d68b2d9
pmaier@sysmocom.de at

#28967 (Jul 9, 2026, 8:37:58 AM)

eIM: use eimTransactionId during profile download

When the eIM initiates a profile download via the
profileDownloadTriggerRequest, it includes an eimTransactionId to identify
sent by the IPAd (testsuite) in the initiateAuthenticationRequestEsipa
response. The eimTransactionId (even though it is optional) is essential
for the eIM to recognize the response from the eIM correctly.

(SGP.32 V.1.0.1 lacked the eimTransactionId, which meant that the eIM had
to rely on other identifiers such as the TCP connection itself. The problem
is now fixed with SGP.32 V.1.2)

Related: SYS#8100
Change-Id: I045d93b9f40ddfb3dc6dfbd9602e736bbc6b4abc
pmaier@sysmocom.de at

#28966 (Jul 9, 2026, 8:37:49 AM)

eIM: add testcase to test an unsuccessful eUICC data request

When we test the ipaEuiccDataRequest/IpaEuiccDataResponse, we currently
only test the success case. However, we should also test the failure
case, bceause an IpaEuiccDataResponseError can also contain an
eimTransactionId, which has to be equal to the eimTransactionId we have
received with the ipaEuiccDataRequest

Related: SYS#8100
Change-Id: Ied212eb636cf46df5fc9f86ddee15c242c50d45a
pmaier@sysmocom.de at

#28965 (Jul 9, 2026, 8:37:44 AM)

eIM, IPAd: migrate from SGP.32 V.1.0.1 to SGP.32 V.1.2

SGP.32 V.1.2 is not backward compatible to SGP.32 V.1.0.1. This patch updates
the ASN.1 specification and the TTCN3 templates and types accordingly.

It also applies the bare minimum of changes required to compile the eIM and IPAd
testcases.

Related: SYS#8100
Related: SYS#8101
Change-Id: Id9e112669d9ed8caaec0893c55189eb566fe59be
Co-authored-by: Andreas Eversberg <aeversberg@sysmocom.de>
pmaier@sysmocom.de at

#28964 (Jul 8, 2026, 3:35:13 PM)

esipa: rename TransactionId to EimTransactionId where applicable

In SGP.32 V.1.2 all TransactionIds which are generated by the eIM are
called now called "eimTransactionId". Let's make sure that we name
the EimTransactionId variables and atoms (eimTransactionId) accordingly.

Change-Id: Ia97f96c27d5dc4405effd5266de4cdb797849699
Related: SYS#8100
pmaier@sysmocom.de at

#28963 (Jul 8, 2026, 3:35:11 PM)

esipa_asn1_handler: use eimTransactionId for ipaEuiccDataResponse

The ipaEuiccDataResponse does currently not use the eimTransactionId,
which was added with SGP.32 V.1.2, let's make use of the eimTransactionId
and move the handler functionality to a dedicated helper function in
esipa_asn_handler_utils.

Change-Id: Ie414eef7fd5c8928dd611503f4dd8d67322c0e80
Related: SYS#8100
pmaier@sysmocom.de at

#28962 (Jul 8, 2026, 3:35:09 PM)

esipa_asn1_handler: use eimTransactionId in EimPackageResultResponseError

EimPackageResultResponseError contains an eimTransactionId, let's use this
eimTransactionId and add a dedicated handler function for the
EimPackageResultResponseError to esipa_asn1_handler_utils

Change-Id: Iadd852a7531f180618cf12b314170ceea3f97615
Related: SYS#8100
pmaier@sysmocom.de at

#28961 (Jul 8, 2026, 3:35:07 PM)

esipa: supply eimTransactionId in profileDownloadTriggerRequest

When we supply an eimTransactionId in profileDownloadTriggerRequest,
the IPAd will echo the same eimTransactionId in the
initiateAuthenticationRequestEsipa message. This allows the eIM
to distinguish to which transaction (work) the received
initiateAuthenticationRequestEsipa belongs. This was not possible
before. The eIM had to rely soly on the PID of the sub process
which is handling the HTTP connection.

Change-Id: I822d6b2bb51498713739671804b173260e9a28a3
Related: SYS#8100
pmaier@sysmocom.de at

#28960 (Jul 8, 2026, 3:35:03 PM)

esipa_asn1_handler_utils: use maps:find

We can replace maps:is_key and maps:get with a single maps:find call.

Change-Id: I6cc151deef161f3ca4726e6b81ae1f5cc80ad184
Related: SYS#8100
pmaier@sysmocom.de at

#28959 (Jul 8, 2026, 3:35:01 PM)

esipa_asn1_handler_utils: rename EsipaReq to Debuginfo

The parameter EsipaReq only exists because we pass it as
Debuginfo to mnesia_db_work:finish. Let's rename it to
"Debuginfo" in esipa_asn1_handler_utils as well to make
clear what the purpose of this parameter is.

Change-Id: I8115d382172989b9ef7ae7f97ce39520e3e2dd16
Related: SYS#8100
pmaier@sysmocom.de at

#28958 (Jul 8, 2026, 3:34:54 PM)

esipa_asn1_handler: replace handle_asn1_notificationList

The helper function handle_asn1_notificationList can also be
described using the comprehension syntax.

Change-Id: Ia95f56998b4f7a8b0f9fce727d82dedc942e5aeb
Related: SYS#8100
pmaier@sysmocom.de at

#28957 (Jul 8, 2026, 3:34:51 PM)

mnesia_db_euicc: rename timer_setparam to timer_rest

The function timer_setparam is processing REAT api orders
in regular intervals. Naming the timer "timer_rest" makes
more sense.

Change-Id: Icfa203477e044ce2cc312d4b6e2693a97191c61d
pmaier@sysmocom.de at

#28956 (Jul 8, 2026, 2:59:10 PM)

eIM, IPAd: migrate from SGP.32 V.1.0.1 to SGP.32 V.1.2

SGP.32 V.1.2 is not backward compatible to SGP.32 V.1.0.1. This patch updates
the ASN.1 specification and the TTCN3 templates and types accordingly.

It also applies the bare minimum of changes required to compile the eIM and IPAd
testcases.

Related: SYS#8100
Related: SYS#8101
Change-Id: Id9e112669d9ed8caaec0893c55189eb566fe59be
Co-authored-by: Andreas Eversberg <aeversberg@sysmocom.de>
pmaier@sysmocom.de at

#28955 (Jul 8, 2026, 2:58:58 PM)

eIM: use eimTransactionId during profile download

When the eIM initiates a profile download via the
profileDownloadTriggerRequest, it includes an eimTransactionId to identify
sent by the IPAd (testsuite) in the initiateAuthenticationRequestEsipa
response. The eimTransactionId (even though it is optional) is essential
for the eIM to recognize the response from the eIM correctly.

(SGP.32 V.1.0.1 lacked the eimTransactionId, which meant that the eIM had
to rely on other identifiers such as the TCP connection itself. The problem
is now fixed with SGP.32 V.1.2)

Related: SYS#8100
Change-Id: I045d93b9f40ddfb3dc6dfbd9602e736bbc6b4abc
pmaier@sysmocom.de at

#28954 (Jul 8, 2026, 2:58:48 PM)

eIM: echo eimTransactionId from euiccDataReq in provideEimPackageResult

The udted eIM now includes an eimTransactionId in its ipaEuiccDataRequest
message, which means that the IPAd (testsuite) has to echo that exact
same eimTransactionId in the IpaEuiccData of the IpaEuiccDataResponse

Related: SYS#8100
Change-Id: I286362e6499eb9440e006f08b7c142c6dfd98843
pmaier@sysmocom.de at

#28953 (Jul 8, 2026, 2:58:44 PM)

eIM, add new PSMOs introduced with SGP.32 V.1.2

SGP.32 V.1.2 adds new PSMOs, which are setFallbackAttribute,
unsetFallbackAttribute and setDefaultDpAddress. Let's add testcases
for those.

Related: SYS#8100
Change-Id: Ic2416dc06d917228b71c61da9acebed26d68b2d9
pmaier@sysmocom.de at

#28952 (Jul 8, 2026, 2:58:39 PM)

eIM: add testcase to test an unsuccessful eUICC data request

When we test the ipaEuiccDataRequest/IpaEuiccDataResponse, we currently
only test the success case. However, we should also test the failure
case, bceause an IpaEuiccDataResponseError can also contain an
eimTransactionId, which has to be equal to the eimTransactionId we have
received with the ipaEuiccDataRequest

Related: SYS#8100
Change-Id: Ied212eb636cf46df5fc9f86ddee15c242c50d45a
pmaier@sysmocom.de at

#28951 (Jul 8, 2026, 2:58:32 PM)

eIM, REST: use template to encode eimConfigurationData

We currently use a hardcoded binary blob for the testcases that test the
addEim and updateEim eCOs. Let's use the enc_EimConfigurationData encoder
function, which we already have, to encode the eimConfigurationData
instead.

Related: SYS#8100
Change-Id: Ic51731da355cd9a209837d4015c02943367ed90b
pmaier@sysmocom.de at

#28950 (Jul 8, 2026, 2:27:32 PM)

eIM: add testcase to test an unsuccessful eUICC data request

When we test the ipaEuiccDataRequest/IpaEuiccDataResponse, we currently
only test the success case. However, we should also test the failure
case, bceause an IpaEuiccDataResponseError can also contain an
eimTransactionId, which has to be equal to the eimTransactionId we have
received with the ipaEuiccDataRequest

Related: SYS#8100
Change-Id: Ied212eb636cf46df5fc9f86ddee15c242c50d45a
pmaier@sysmocom.de at

#28949 (Jul 8, 2026, 2:27:28 PM)

eIM: use eimTransactionId during profile download

When the eIM initiates a profile download via the
profileDownloadTriggerRequest, it includes an eimTransactionId to identify
sent by the IPAd (testsuite) in the initiateAuthenticationRequestEsipa
response. The eimTransactionId (even though it is optional) is essential
for the eIM to recognize the response from the eIM correctly.

(SGP.32 V.1.0.1 lacked the eimTransactionId, which meant that the eIM had
to rely on other identifiers such as the TCP connection itself. The problem
is now fixed with SGP.32 V.1.2)

Related: SYS#8100
Change-Id: I045d93b9f40ddfb3dc6dfbd9602e736bbc6b4abc
pmaier@sysmocom.de at

#28948 (Jul 8, 2026, 2:27:21 PM)

eIM: echo eimTransactionId from euiccDataReq in provideEimPackageResult

The udted eIM now includes an eimTransactionId in its ipaEuiccDataRequest
message, which means that the IPAd (testsuite) has to echo that exact
same eimTransactionId in the IpaEuiccData of the IpaEuiccDataResponse

Related: SYS#8100
Change-Id: I286362e6499eb9440e006f08b7c142c6dfd98843
pmaier@sysmocom.de at

#28947 (Jul 8, 2026, 2:27:15 PM)

eIM, IPAd: migrate from SGP.32 V.1.0.1 to SGP.32 V.1.2

SGP.32 V.1.2 is not backward compatible to SGP.32 V.1.0.1. This patch updates
the ASN.1 specification and the TTCN3 templates and types accordingly.

It also applies the bare minimum of changes required to compile the eIM and IPAd
testcases.

Related: SYS#8100
Related: SYS#8101
Change-Id: Id9e112669d9ed8caaec0893c55189eb566fe59be
Co-authored-by: Andreas Eversberg <aeversberg@sysmocom.de>
pmaier@sysmocom.de at

#28946 (Jul 8, 2026, 10:57:36 AM)

esipa_asn1_handler: replace handle_asn1_notificationList

The helper function handle_asn1_notificationList can also be
described using the comprehension syntax.

Change-Id: Ia95f56998b4f7a8b0f9fce727d82dedc942e5aeb
Related: SYS#8100
pmaier@sysmocom.de at

#28945 (Jul 8, 2026, 10:57:33 AM)

esipa: supply eimTransactionId in profileDownloadTriggerRequest

When we supply an eimTransactionId in profileDownloadTriggerRequest,
the IPAd will echo the same eimTransactionId in the
initiateAuthenticationRequestEsipa message. This allows the eIM
to distinguish to which transaction (work) the received
initiateAuthenticationRequestEsipa belongs. This was not possible
before. The eIM had to rely soly on the PID of the sub process
which is handling the HTTP connection.

Change-Id: I822d6b2bb51498713739671804b173260e9a28a3
Related: SYS#8100
pmaier@sysmocom.de at

#28944 (Jul 8, 2026, 10:57:31 AM)

esipa_asn1_handler_utils: rename EsipaReq to Debuginfo

The parameter EsipaReq only exists because we pass it as
Debuginfo to mnesia_db_work:finish. Let's rename it to
"Debuginfo" in esipa_asn1_handler_utils as well to make
clear what the purpose of this parameter is.

Change-Id: I8115d382172989b9ef7ae7f97ce39520e3e2dd16
Related: SYS#8100
pmaier@sysmocom.de at

#28943 (Jul 8, 2026, 10:57:29 AM)

esipa_asn1_handler: use eimTransactionId for ipaEuiccDataResponse

The ipaEuiccDataResponse does currently not use the eimTransactionId,
which was added with SGP.32 V.1.2, let's make use of the eimTransactionId
and move the handler functionality to a dedicated helper function in
esipa_asn_handler_utils.

Change-Id: Ie414eef7fd5c8928dd611503f4dd8d67322c0e80
Related: SYS#8100
pmaier@sysmocom.de at

#28942 (Jul 8, 2026, 10:57:25 AM)

esipa_asn1_handler: use eimTransactionId in EimPackageResultResponseError

EimPackageResultResponseError contains an eimTransactionId, let's use this
eimTransactionId and add a dedicated handler function for the
EimPackageResultResponseError to esipa_asn1_handler_utils

Change-Id: Iadd852a7531f180618cf12b314170ceea3f97615
Related: SYS#8100
pmaier@sysmocom.de at

#28941 (Jul 8, 2026, 10:57:22 AM)

esipa: rename TransactionId to EimTransactionId where applicable

In SGP.32 V.1.2 all TransactionIds which are generated by the eIM are
called now called "eimTransactionId". Let's make sure that we name
the EimTransactionId variables and atoms (eimTransactionId) accordingly.

Change-Id: Ia97f96c27d5dc4405effd5266de4cdb797849699
Related: SYS#8100
pmaier@sysmocom.de at

#28940 (Jul 8, 2026, 10:48:37 AM)

mnesia_db: split functionality into dedicated modules

The mnesia_db module is responsible to handle three different tables
with different scope. Let's split the functionality into separate
modules to make the code easier to maintain.

Change-Id: Ifc649337ab7ce7eb9dc602a1439293130f002f41
Related: SYS#8100
pmaier@sysmocom.de at

#28939 (Jul 8, 2026, 10:31:13 AM)

mnesia_db: split functionality into dedicated modules

The mnesia_db module is responsible to handle three different tables
with different scope. Let's split the functionality into separate
modules to make the code easier to maintain.

Change-Id: Ifc649337ab7ce7eb9dc602a1439293130f002f41
Related: SYS#8100
pmaier@sysmocom.de at

#28938 (Jul 8, 2026, 10:17:07 AM)

esipa_asn1_handler: use eimTransactionId for ipaEuiccDataResponse

The ipaEuiccDataResponse does currently not use the eimTransactionId,
which was added with SGP.32 V.1.2, let's make use of the eimTransactionId
and move the handler functionality to a dedicated helper function in
esipa_asn_handler_utils.

Change-Id: Ie414eef7fd5c8928dd611503f4dd8d67322c0e80
Related: SYS#8100
pmaier@sysmocom.de at

#28937 (Jul 8, 2026, 10:17:05 AM)

esipa: rename TransactionId to EimTransactionId where applicable

In SGP.32 V.1.2 all TransactionIds which are generated by the eIM are
called now called "eimTransactionId". Let's make sure that we name
the EimTransactionId variables and atoms (eimTransactionId) accordingly.

Change-Id: Ia97f96c27d5dc4405effd5266de4cdb797849699
Related: SYS#8100
pmaier@sysmocom.de at

#28936 (Jul 8, 2026, 10:17:03 AM)

esipa_asn1_handler_utils: rename EsipaReq to Debuginfo

The parameter EsipaReq only exists because we pass it as
Debuginfo to mnesia_db_work:finish. Let's rename it to
"Debuginfo" in esipa_asn1_handler_utils as well to make
clear what the purpose of this parameter is.

Change-Id: I8115d382172989b9ef7ae7f97ce39520e3e2dd16
Related: SYS#8100
pmaier@sysmocom.de at

#28935 (Jul 8, 2026, 10:16:59 AM)

esipa_asn1_handler: use eimTransactionId in EimPackageResultResponseError

EimPackageResultResponseError contains an eimTransactionId, let's use this
eimTransactionId and add a dedicated handler function for the
EimPackageResultResponseError to esipa_asn1_handler_utils

Change-Id: Iadd852a7531f180618cf12b314170ceea3f97615
Related: SYS#8100
pmaier@sysmocom.de at

#28934 (Jul 8, 2026, 10:16:56 AM)

esipa_asn1_handler: replace handle_asn1_notificationList

The helper function handle_asn1_notificationList can also be
described using the comprehension syntax.

Change-Id: Ia95f56998b4f7a8b0f9fce727d82dedc942e5aeb
Related: SYS#8100
pmaier@sysmocom.de at

#28933 (Jul 8, 2026, 10:16:53 AM)

esipa: supply eimTransactionId in profileDownloadTriggerRequest

When we supply an eimTransactionId in profileDownloadTriggerRequest,
the IPAd will echo the same eimTransactionId in the
initiateAuthenticationRequestEsipa message. This allows the eIM
to distinguish to which transaction (work) the received
initiateAuthenticationRequestEsipa belongs. This was not possible
before. The eIM had to rely soly on the PID of the sub process
which is handling the HTTP connection.

Change-Id: I822d6b2bb51498713739671804b173260e9a28a3
Related: SYS#8100
pmaier@sysmocom.de at

#28932 (Jul 8, 2026, 10:09:43 AM)

esipa_rest_utils: re-align to SGP.32 Section 2.11.2

Section 2.11.2: rename EuiccPackageResultDataSigned.configureAutoEnableResult to EuiccPackageResultDataSigned.configureImmediateEnableResult

Change-Id: Ib4e6a4b4cb4d26a391346169b9047515496dd308
Related: SYS#8100
pmaier@sysmocom.de at

#28931 (Jul 8, 2026, 10:09:39 AM)

mnesia_db: split functionality into dedicated modules

The mnesia_db module is responsible to handle three different tables
with different scope. Let's split the functionality into separate
modules to make the code easier to maintain.

Change-Id: Ifc649337ab7ce7eb9dc602a1439293130f002f41
Related: SYS#8100
pmaier@sysmocom.de at

#28930 (Jul 8, 2026, 10:09:35 AM)

esipa_asn1_handler: re-align to SGP.32 section 2.11.2 and section 5.14.6

Section 2.11.2: eIM package result (EuiccPackageResult case) is now concatenated with PendingNotificationList instead of RetrieveNotificationsListResponse
Section 5.14.6: ESipa.ProvideEimPackageResult: Significant change in parameters

Change-Id: Ic0872edefc1844166943c60528557c6b7a6602ce
Related: SYS#8100
pmaier@sysmocom.de at

#28929 (Jul 8, 2026, 10:09:32 AM)

es9p_client: convert InitiateAuthenticationOkEsipa to match SGP.32 V.1.2

In SGP.32 V.1.0.1, InitiateAuthenticationOkEsipa is almost identical to
SGP.22 InitiateAuthenticationOkEs9. However, in SGP.32 V.1.2, the member
euiccCiPKIdToBeUsed is renamed to euiccCiPKIdentifierToBeUsed. This means
it is no longer possible to pass InitiateAuthenticationOkEsipa as
InitiateAuthenticationOkEs9 to ES9+ directly. Instead we have to re-build
the the InitiateAuthenticationOkEs9 from the contents of
InitiateAuthenticationOkEsipa.

Change-Id: I44c60a2f0d1129093ea67908d2eed167643a4a87
Related: SYS#8100
pmaier@sysmocom.de at

#28928 (Jul 8, 2026, 10:02:11 AM)

eim_cfg: set eimSupportedProtocol and indirectProfileDownload flags

The members eimSupportedProtocol and indirectProfileDownload were
added as optional members to EimConfigurationData with SGP.32 V.1.2.

Since our eIM implementation only supports eIM Package Retrieval via
HTTPs and the Indirect Profile Download procedure is the only Profile
Download procedure we currently support, the EimConfigurationData
should reflect those properties correctly.

(The EimConfigurationData is not announced actively by the eIM, but
this eIM implementation contains a generator to help with the encoding
of the EimConfigurationData that is programmed into the eUICC)

Change-Id: I4ce236fb1bfb8a3790191be95ab0958dce13a9d8
Related: SYS#8100
pmaier@sysmocom.de at

#28927 (Jul 8, 2026, 9:24:28 AM)

esipa_asn1_handler: fix transactionId handling

The transactionId member is now called eimTransactionId. It is also
an optional member.

Change-Id: I1340e0c7aed091e8e5a5089ebd6e524512408cf7
Related: SYS#8100
pmaier@sysmocom.de at

#28926 (Jul 8, 2026, 9:24:25 AM)

esipa_asn1_codec: add special handling for ProvideEimPackageResultResponse

In SGP.32 V.1.2 ProvideEimPackageResultResponse is defined as a CHOICE.
This means that this struct now also requires special handling.

Change-Id: I859a175cc28a18ea9334d9b2cf233294fdc95b76
Related: SYS#8100
pmaier@sysmocom.de at

#28925 (Jul 8, 2026, 7:43:51 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
(cherry picked from commit a013155e8af1b4cca604e10f81dcb683a5e7812c)
Oliver Smith at

#28924 (Jul 8, 2026, 7:43:48 AM)

Bump version: 0.4.1

Change-Id: I17c9806400a48b4cdf7be19a824e10c56620d655
Oliver Smith at

#28923 (Jul 8, 2026, 6:49:01 AM)

Bump version: 0.9.0.4-3248-dirty → 0.9.1

Change-Id: I0d06c6f15aa99be7609eac9afb6b9df8e6cf3dc5
Oliver Smith at

#28922 (Jul 7, 2026, 1:57:44 PM)

Add missing const for struct hostent *hostent

The hostent parameter is supposed to be const. This is being enforced in
c-ares 1.34.7, which is why osmo-sgsn currently fails to build in debian
unstable. The c-ares developers are preparing a new release that reverts
this change to avoid breakage with other users of libc-ares, and only
document that this should basically be const. But let's use the API as
intended so the compiler knows that osmo-sgsn is not supposed to modify
the hostent parameter.

Fix for:

  sgsn_ares.c:141:63: error: passing argument 4 of 'ares_gethostbyname' from incompatible pointer type [-Wincompatible-pointer-types]
    141 |         ares_gethostbyname(sgsn->ares_channel, name, AF_INET, ares_cb, cb_data);
        |                                                               ^~~~~~~
        |                                                               |
        |                                                               void (*)(void *, int,  int,  struct hostent *)
  /usr/include/ares.h:881:22: note: expected 'ares_host_callback' {aka 'void (*)(void *, int,  int,  const struct hostent *)'} but argument is of type 'void (*)(void *, int,  int,  struct hostent *)'

Related: https://github.com/c-ares/c-ares/pull/1060
Related: https://github.com/c-ares/c-ares/pull/1244
Change-Id: Ibe3debc5d3b7af5883001960c40efb296692f93d
Oliver Smith at

#28921 (Jul 7, 2026, 11:50:55 AM)

Revert "OBS: sync_obs_projects: remove AlmaLinux:8"

This reverts commit 618140a22e41cba21ac2cfac51a84c7514041657.

Related: SYS#8110
Change-Id: Idbaeed2af6441b15f11ca7cf1b7563a99586ed85
Oliver Smith at

#28920 (Jul 7, 2026, 11:50:51 AM)

OBS: build_binpkg: adjust for new almalinux repo

We are enabling CentOS 8 compatible repositories again for very few
packages. The URL for the package feed is now AlmaLinux_8 instead of
CentOS_8, because AlmaLinux 8 is not EOL yet and seems to work best with
OBS of the CentOS 8 compatible distros.

Related: SYS#8110
Change-Id: I3e9f44f200cdbe28fa4cd21f54b81d73fa543075
Oliver Smith at

#28919 (Jul 7, 2026, 11:50:47 AM)

contrib/obs-mirror: add AlmaLinux_8

Related: SYS#8110
Change-Id: I8ebf9d613e9ce8ee0982dd68646f248148ac6226
Oliver Smith at

#28918 (Jul 7, 2026, 11:50:43 AM)

jobs/gerrit: build osmo-pcap + deps for almalinux8

Related: SYS#8110
Change-Id: I8ba119b77f7bb04b0899af8c09ac35782625425a
Oliver Smith at

#28917 (Jul 7, 2026, 7:43:38 AM)

deps: use a fork of titan.ProtocolEmulations.SCCP

Change-Id: I8c0de4dab088930d5d7a9febcbebcb5e1f9411e8
dwillmann at

#28916 (Jul 7, 2026, 7:43:30 AM)

stp: add ASP_SCCP_N_NOTICE_req support and f_asp_tx_notice()

Wire ASP_SCCP_N_NOTICE_req as a simple passthrough in TCAP_CODEC_PT,
so test components can send UDTS via the existing SCCP_TCAP port.
Add f_asp_tx_notice() to STP_Tests_TCAP as a convenience wrapper.

Change-Id: I74c05405f1c99d43b4bf863f959275ee51301f2e
dwillmann at

#28915 (Jul 7, 2026, 7:43:19 AM)

stp: Add TCAP_N_NOTICE_req to send a UDTS with TCAP payload

Change-Id: Ie13cecc2f2fc8a20d9646f0fb010b91c2ecf7766
dwillmann at

#28914 (Jul 7, 2026, 7:43:12 AM)

stp: Test that UDTS containing tcap is routed correctly

Related: SYS#8090
Depends: libosmo-sigtran.git I2051aa9e84e553feb17daabb93ba3ce82358e0e4
Change-Id: I264ab424fbc3652249535bbe4f30029defa64c09
dwillmann at

#28913 (Jul 7, 2026, 7:38:03 AM)

tcap_as_loadshare: Forward UDTS to the correct tcap-loadshare ASP

Related: SYS#8090
Change-Id: I2051aa9e84e553feb17daabb93ba3ce82358e0e4
dwillmann at

#28912 (Jul 7, 2026, 7:36:39 AM)

STP_Tests_TCAP: Test routing of fragments in TC_tcap_loadshare_ipa_tcap_range_success_pc

A TCAP Begin will cause the stp to create a cache entry and route
according to that. Send only a TCAP Continue so we check the tcap range
routing logic.

Change-Id: I1cb47174b8f0e69970e75109b9d15b2012e150c3
dwillmann at

#28911 (Jul 7, 2026, 7:36:33 AM)

STP_Tests_TCAP: Fix ipa_to_ipa testcase

tcap routing doesn't work the way the test thinks. E.g. a Begin can't be
routed to a special destination because it does't contain a dtid which
is needed to route to the correct ASP.

Change-Id: Ie274232b706348b5ab6d0ac248883d86c53ebb4e
dwillmann at

#28910 (Jul 2, 2026, 9:35:58 AM)

redmine: upgrade to 6.1.3

* Use the redmine:6.1.3 image from upstream (the sysmocom registry image
  was a workaround for 5.1.11).

* Install nkf with native extensions (needs gcc, libc6-dev, make) for
  the redmine_openid_provider plugin. This was not needed for the
  redmine 5 container, it was probably bundled there already.

* Upgrade "activerecord-session_store" to version 2.2.0, which is
  compatible with redmine 6.

Related: SYS#8097
Change-Id: I3e7f746b1a96ff98bbdea2e043a88b9a492672d2
Oliver Smith at

#28909 (Jul 1, 2026, 1:29:57 PM)

5gc: disable TC_handover_inter_ngran_xn for latest

Temporarily disable the test for latest as it is known to result in a
crash with open5gs v2.8.0.

Related: OS#7023
Change-Id: Ibf3683683093c41a85bb443e14eab23d23fefa24
Oliver Smith at

#28908 (Jul 1, 2026, 11:58:27 AM)

redmine: upgrade to 6.1.3

Related: SYS#8097
Change-Id: I3e7f746b1a96ff98bbdea2e043a88b9a492672d2
Oliver Smith at

#28907 (Jul 1, 2026, 11:47:46 AM)

library: add f_gsm_fn_{sum,sub,diff}()

Change-Id: Ie91ccef5d3f170f4a341a6cf9d3323a896b299e6
Vadim Yanitskiy at

#28906 (Jul 1, 2026, 11:47:42 AM)

bts: TC_pcu_interf_ind: check reporting interval instead of absolute FN

Recent osmo-bts commit 53f0ec29 broke TC_pcu_interf_ind:

  Verdict: fail reason: Odd TDMA frame number := 935

There's no requirement that periodic interference reports must land
on a TDMA frame number satisfying 'fn mod 104 == 0' - only that they
keep arriving every configured averaging period.  Instead, verify
that the interval between consecutive reports equals 104 TDMA frames
(1 SACCH period), using the new f_gsm_fn_sub() helper.

Change-Id: Ia96f2926400bae8c0a6fb8f81eb56b48ca5f2de9
Related: 53f0ec29 ("l1sap: fix duplicate RF RESOURCE INDICATION on clock bootstrap")
Vadim Yanitskiy at

#28905 (Jul 1, 2026, 11:15:06 AM)

library: add f_gsm_fn_{sum,sub,diff}()

Change-Id: Ie91ccef5d3f170f4a341a6cf9d3323a896b299e6
Vadim Yanitskiy at

#28904 (Jul 1, 2026, 11:15:02 AM)

bts: TC_pcu_interf_ind: check reporting interval instead of absolute FN

Recent osmo-bts commit 53f0ec29 broke TC_pcu_interf_ind:

  Verdict: fail reason: Odd TDMA frame number := 935

There's no requirement that periodic interference reports must land
on a TDMA frame number satisfying 'fn mod 104 == 0' - only that they
keep arriving every configured averaging period.  Instead, verify
that the interval between consecutive reports equals 104 TDMA frames
(1 SACCH period), using the new f_gsm_fn_sub() helper.

Change-Id: Ia96f2926400bae8c0a6fb8f81eb56b48ca5f2de9
Related: 53f0ec29 ("l1sap: fix duplicate RF RESOURCE INDICATION on clock bootstrap")
Vadim Yanitskiy at

#28903 (Jul 1, 2026, 9:48:54 AM)

pySim.log: fix E0611: No name 'style' in module 'cmd2'

Change-Id: I191ea56f4c6e4e1916369f69fe2e1653e1d92df1
Fixes: 597f1e0 ("pySim.log, pySim-shell: fix compatibility with cmd2 >= 3.0.0")
Vadim Yanitskiy at

#28902 (Jun 30, 2026, 4:25:48 PM)

common: reset lchan meas state in gsm_lchan_release()

lchan->meas (including interf_meas_num and num_ul_meas) is normally
only reset by lchan_meas_reset() called from rsl_tx_chan_act_ack() on
RSL CHANNEL ACTIVATION.  Idle logical channels are never RSL-activated,
so their measurement state is never reset via that path.

On an OML link re-establishment, osmo-bts does not exit: abis.c tears
down the signalling links, the bts_shutdown FSM powers down all TRXs,
and then waits for reconnect.  The gsm_bts/trx/ts/lchan structures
remain in memory, so stale interf_meas_num survives the reconnect.

This is why we're seeing these ERRORs while running ttcn3-bts-test:

(bts=0,trx=2,ts=4,ss=6) Not enough room to store interference report (0dBm)

Add a lchan_meas_reset() call to gsm_lchan_release(), which is called
from gsm_ts_release() when the nm_channel_fsm enters state
NM_CHAN_ST_OP_DISABLED_NOTINSTALLED.  This is exactly the right
moment: the radio is fully stopped, so no new samples arrive.

Change-Id: I18dc9d30417b0c5b2e579660d4a087d93445f956
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28901 (Jun 30, 2026, 4:25:44 PM)

common: stop buffering UL measurements when SACCH is deactivated

When the BSC sends RSL DEACT SACCH, the per-SACCH UL measurement drain
stops (it runs on SACCH timing), but the producer in lchan_new_ul_meas()
keeps appending the measurement contributions from every received
TCH/SDCCH burst.  After one SACCH period (104 frames) the 104-slot
uplink measurement buffer fills up, yielding a flood of:

  NOTICE measurement.c:336 no space for uplink measurement, num_ul_meas=104

Add a bool sacch_active flag to gsm_lchan, set to true in the common
l1sap_chan_act() and clear in l1sap_chan_deact_sacch().  Guard
lchan_new_ul_meas() with this flag so that measurements are silently
discarded while SACCH is inactive - there is nothing to drain the
buffer and no SACCH channel on which to report the results to the BSC.

Change-Id: I3943c788cab5d2411b06ac681d4d412852bac0a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28900 (Jun 30, 2026, 4:22:27 PM)

common: flush paging queue in nm_bts_fsm's NOTINSTALLED on_enter

paging_reset() exists to flush stale paging records from the queue,
but was never called anywhere.  Stale paging records can accumulate
when the OML link goes down: osmo-bts does not exit, so the paging
queue survives into the next BSC session.

Call it alongside bts_cbch_reset() and bts_asci_notification_reset()
in st_op_disabled_notinstalled_on_enter(), which fires after all TRXs
are confirmed closed and before a new OML connection is accepted.

Change-Id: I109ab282986b68b68ba5c11859c44b771c0416fd
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28899 (Jun 30, 2026, 3:28:42 PM)

rest_api_response_schema: add missing error codes

In SGP.32 V.1.2, new error codes were added to EnableProfileResult,
DisableProfileResult, DeleteProfileResult and AddEimResult

See also: SGP.32, section 2.11.2

Change-Id: I525ca9d3b7fb870405d374160272d8ec26c85880
Related: SYS#8100
pmaier@sysmocom.de at

#28898 (Jun 30, 2026, 3:26:42 PM)

esipa_rest_utils: align IpaEuiccDataResponse to SGP.32 V.1.2

The ASN.1 struct IpaEuiccDataResponse has renamed the error code
member from ipaEuiccDataError to ipaEuiccDataErrorCode. The new
ipaEuiccDataErrorCode is a sequence that has an ipaEuiccDataErrorCode
member, which is the equivalent of the previously existing
ipaEuiccDataError member.

See also: SGP.32, section 2.11.2.2

Change-Id: Ie734a09ed4b0d57de30dc6fb377dfada79ea2ae4
Related: SYS#8100
pmaier@sysmocom.de at

#28897 (Jun 30, 2026, 3:24:07 PM)

esipa_rest_utils: add support for PSMOs added in SGP.32 V.1.2

SGP.32 adds 3 additional PSMOs:
- setFallbackAttribute
- unsetFallbackAttribute
- setDefaultDpAddress

Change-Id: I03cdd70065a83dfc611d614cf32d817c13fad347
Related: SYS#8100
pmaier@sysmocom.de at

#28896 (Jun 30, 2026, 3:20:12 PM)

esipa_rest_utils: add support for PSMOs added in SGP.32 V.1.2

SGP.32 adds 3 additional PSMOs:
- setFallbackAttribute
- unsetFallbackAttribute
- setDefaultDpAddress

Change-Id: I03cdd70065a83dfc611d614cf32d817c13fad347
Related: SYS#8100
pmaier@sysmocom.de at

#28895 (Jun 30, 2026, 3:14:26 PM)

rest_api: move "required" member to the correct level

In some locations in the JSON schema files we find the "required"
member on the same level as the members of "properties" (likewise
"items"). This is incorrect, the "required" member should always
be on the same level as the "properties" or "items" member.

(At the moment the JSON schema files serve only documentation
purposes, they are not used to do any actual validation yet.)

Change-Id: I07d51d0e809a718144bd51a6540ab51187bb4daa
Related: SYS#8100
pmaier@sysmocom.de at

#28894 (Jun 30, 2026, 3:12:07 PM)

eim_cfg: set eimSupportedProtocol and indirectProfileDownload flags

The members eimSupportedProtocol and indirectProfileDownload were
added as optional members to EimConfigurationData with SGP.32 V.1.2.

Since our eIM implementation only supports eIM Package Retrieval via
HTTPs and the Indirect Profile Download procedure is the only Profile
Download procedure we currently support, the EimConfigurationData
should reflect those properties correctly.

(The EimConfigurationData is not announced actively by the eIM, but
this eIM implementation contains a generator to help with the encoding
of the EimConfigurationData that is programmed into the eUICC)

Change-Id: I4ce236fb1bfb8a3790191be95ab0958dce13a9d8
Related: SYS#8100
pmaier@sysmocom.de at

#28893 (Jun 30, 2026, 3:10:12 PM)

esipa_rest_utils: re-align to SGP.32 Section 2.11.2

Section 2.11.2: rename EuiccPackageResultDataSigned.configureAutoEnableResult to EuiccPackageResultDataSigned.configureImmediateEnableResult

Change-Id: Ib4e6a4b4cb4d26a391346169b9047515496dd308
Related: SYS#8100
pmaier@sysmocom.de at

#28892 (Jun 30, 2026, 3:03:05 PM)

esipa_rest_utils: re-align to SGP.32 Section 2.11.2

Section 2.11.2: rename EuiccPackageResultDataSigned.configureAutoEnableResult to EuiccPackageResultDataSigned.configureImmediateEnableResult

Change-Id: Ib4e6a4b4cb4d26a391346169b9047515496dd308
Related: SYS#8100
pmaier@sysmocom.de at

#28891 (Jun 30, 2026, 3:03:01 PM)

eim_cfg: set eimSupportedProtocol and indirectProfileDownload flags

The members eimSupportedProtocol and indirectProfileDownload were
added as optional members to EimConfigurationData with SGP.32 V.1.2.

Since our eIM implementation only supports eIM Package Retrieval via
HTTPs and the Indirect Profile Download procedure is the only Profile
Download procedure we currently support, the EimConfigurationData
should reflect those properties correctly.

(The EimConfigurationData is not announced actively by the eIM, but
this eIM implementation contains a generator to help with the encoding
of the EimConfigurationData that is programmed into the eUICC)

Change-Id: I4ce236fb1bfb8a3790191be95ab0958dce13a9d8
Related: SYS#8100
pmaier@sysmocom.de at

#28890 (Jun 30, 2026, 3:00:57 PM)

esipa_asn1_handler: re-align to SGP.32 section 2.11.2 and section 5.14.6

Section 2.11.2: eIM package result (EuiccPackageResult case) is now concatenated with PendingNotificationList instead of RetrieveNotificationsListResponse
Section 5.14.6: ESipa.ProvideEimPackageResult: Significant change in parameters

Change-Id: Ic0872edefc1844166943c60528557c6b7a6602ce
Related: SYS#8100
pmaier@sysmocom.de at

#28889 (Jun 30, 2026, 2:40:16 PM)

esipa_asn1_handler: re-align to SGP.32 section 2.11.2 and section 5.14.6

Section 2.11.2: eIM package result (EuiccPackageResult case) is now concatenated with PendingNotificationList instead of RetrieveNotificationsListResponse
Section 5.14.6: ESipa.ProvideEimPackageResult: Significant change in parameters

Change-Id: Ic0872edefc1844166943c60528557c6b7a6602ce
Related: SYS#8100
pmaier@sysmocom.de at

#28888 (Jun 30, 2026, 2:36:00 PM)

esipa_asn1_handler: fix transactionId handling

The transactionId member is now called eimTransactionId. It is also
an optional member.

Change-Id: I1340e0c7aed091e8e5a5089ebd6e524512408cf7
Related: SYS#8100
pmaier@sysmocom.de at

#28887 (Jun 30, 2026, 2:33:35 PM)

esipa_asn1_codec: add special handling for ProvideEimPackageResultResponse

In SGP.32 V.1.2 ProvideEimPackageResultResponse is defined as a CHOICE.
This means that this struct now also requires special handling.

Change-Id: I859a175cc28a18ea9334d9b2cf233294fdc95b76
Related: SYS#8100
pmaier@sysmocom.de at

#28886 (Jun 30, 2026, 2:30:40 PM)

es9p_client: section 6.3.2.1, rename euiccCiPKIdToBeused to match SGP.32 V.1.2

Section 6.3.2.1: rename InitiateAuthenticationOkEsipa.euiccCiPKIdToBeused to InitiateAuthenticationOkEsipa.euiccCiPKIdentifierToBeUsed

Change-Id: I44c60a2f0d1129093ea67908d2eed167643a4a87
Related: SYS#8100
pmaier@sysmocom.de at

#28885 (Jun 30, 2026, 10:46:08 AM)

eim_cfg: set eimSupportedProtocol and indirectProfileDownload flags

The members eimSupportedProtocol and indirectProfileDownload were
added as optional members to EimConfigurationData with SGP.32 V.1.2.

Since our eIM implementation only supports eIM Package Retrieval via
HTTPs and the Indirect Profile Download procedure is the only Profile
Download procedure we currently support, the EimConfigurationData
should reflect those properties correctly.

(The EimConfigurationData is not announced actively by the eIM, but
this eIM implementation contains a generator to help with the encoding
of the EimConfigurationData that is programmed into the eUICC)

Change-Id: I4ce236fb1bfb8a3790191be95ab0958dce13a9d8
Related: SYS#8100
pmaier@sysmocom.de at

#28884 (Jun 30, 2026, 10:10:39 AM)

es9p_client: section 6.3.2.1, rename euiccCiPKIdToBeused to match SGP.32 V.1.2

Section 6.3.2.1: rename InitiateAuthenticationOkEsipa.euiccCiPKIdToBeused to InitiateAuthenticationOkEsipa.euiccCiPKIdentifierToBeUsed

Change-Id: I44c60a2f0d1129093ea67908d2eed167643a4a87
Related: SYS#8100
pmaier@sysmocom.de at

#28883 (Jun 30, 2026, 10:10:37 AM)

esipa_rest_utils: re-align to SGP.32 Section 2.11.2

Section 2.11.2: rename EuiccPackageResultDataSigned.configureAutoEnableResult to EuiccPackageResultDataSigned.configureImmediateEnableResult

Change-Id: Ib4e6a4b4cb4d26a391346169b9047515496dd308
Related: SYS#8100
pmaier@sysmocom.de at

#28882 (Jun 30, 2026, 10:10:35 AM)

esipa_asn1_handler: fix transactionId handling

The transactionId member is now called eimTransactionId. It is also
an optional member.

Change-Id: I1340e0c7aed091e8e5a5089ebd6e524512408cf7
Related: SYS#8100
pmaier@sysmocom.de at

#28881 (Jun 30, 2026, 10:10:31 AM)

esipa_asn1_codec: add special handling for ProvideEimPackageResultResponse

In SGP.32 V.1.2 ProvideEimPackageResultResponse is defined as a CHOICE.
This means that this struct now also requires special handling.

Change-Id: I859a175cc28a18ea9334d9b2cf233294fdc95b76
Related: SYS#8100
pmaier@sysmocom.de at

#28880 (Jun 30, 2026, 10:10:27 AM)

esipa_asn1_handler: re-align to SGP.32 section Section 2.11.2 and Section 5.14.6

Section 2.11.2: eIM package result (EuiccPackageResult case) is now concatenated with PendingNotificationList instead of RetrieveNotificationsListResponse
Section 5.14.6: ESipa.ProvideEimPackageResult: Significant change in parameters

Change-Id: Ic0872edefc1844166943c60528557c6b7a6602ce
Related: SYS#8100
pmaier@sysmocom.de at

#28879 (Jun 30, 2026, 9:55:17 AM)

asn1/SGP32Definitions: apply workarounds

- Some ASN.1 structs from SGP.22 are re-defined under the same name by SGP.32.
  This leads to name clashes, which most ASN.1 compilers have problems with.
  Prefixing the re-defined struct in SGP.32 with "SGP32-" solves the problem.

- The erlang asn1ct ASN.1 compiler seems to misinterpret the ASN.1 spec when
  a context specific tag is used (redundently) on a child struct definition
  and in the parent definition at the same time. Removing te context specific
  tag on the child struct definition solves the problem.

Change-Id: Id90b005fc3c8c8f737b0c740d4c067f90842a1fe
Related: SYS#8100
pmaier@sysmocom.de at

#28878 (Jun 30, 2026, 9:47:22 AM)

asn1/SGP32Definitions: upgrade ASN.1 spec to V.1.2

This replaces the existing SGP.32 V.1.0.1 ASN.1 spec with the
unmodified, official SGP.32 V.1.2 spec.

Unfortunately V.1.2 is not backward compatible to V.1.0.1. This means
that the eIM application will still compile, but the result will be
non-functional. The incompatibility problems will be addressed in
the follow-up patches of this patchset.

Change-Id: Id4d217296f43846aa39f5dc7076465e2dab72a7c
Related: SYS#8100
pmaier@sysmocom.de at

#28877 (Jun 30, 2026, 9:12:02 AM)

rebar.config: bump meck version: 0.9.2 -> v1.2.0

This fixes a compilation error with recent Erlang/OTP 29:

[  335s] ===> Compiling meck
[  335s] ===> Compiling _checkouts/meck/src/meck_matcher.erl failed
[  335s] meck_matcher.erl:76:6: 'catch ...' is deprecated; please use 'try ... catch ... end' instead.
[  335s] Compile directive 'nowarn_deprecated_catch' can be used to suppress
[  335s] warnings in selected modules.

Change-Id: If3409de1e09ac1b6ce3355d19e47ef0e160a2d3b
Vadim Yanitskiy at

#28876 (Jun 29, 2026, 2:54:13 PM)

common: stop buffering UL measurements when SACCH is deactivated

When the BSC sends RSL DEACT SACCH, the per-SACCH UL measurement drain
stops (it runs on SACCH timing), but the producer in lchan_new_ul_meas()
keeps appending the measurement contributions from every received
TCH/SDCCH burst.  After one SACCH period (104 frames) the 104-slot
uplink measurement buffer fills up, yielding a flood of:

  NOTICE measurement.c:336 no space for uplink measurement, num_ul_meas=104

Add a bool sacch_active flag to gsm_lchan, set to true in the common
l1sap_chan_act() and clear in l1sap_chan_deact_sacch().  Guard
lchan_new_ul_meas() with this flag so that measurements are silently
discarded while SACCH is inactive - there is nothing to drain the
buffer and no SACCH channel on which to report the results to the BSC.

Change-Id: I3943c788cab5d2411b06ac681d4d412852bac0a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28875 (Jun 29, 2026, 1:56:23 PM)

common: flush paging queue in nm_bts_fsm's NOTINSTALLED on_enter

paging_reset() exists to flush stale paging records from the queue,
but was never called anywhere.  Stale paging records can accumulate
when the OML link goes down: osmo-bts does not exit, so the paging
queue survives into the next BSC session.

Call it alongside bts_cbch_reset() and bts_asci_notification_reset()
in st_op_disabled_notinstalled_on_enter(), which fires after all TRXs
are confirmed closed and before a new OML connection is accepted.

Change-Id: I109ab282986b68b68ba5c11859c44b771c0416fd
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28874 (Jun 29, 2026, 1:56:18 PM)

l1sap: fix duplicate RF RESOURCE INDICATION on clock bootstrap

The TTCN-3 test suite (ttcn3-bts-test) expects to receive exactly one
RF RESOURCE INDICATION message from each TRX during the bootstrap stage,
while waiting for all TRX to come up and be configured by the BSC.

l1sap_interf_meas_report() fires whenever bts->gsm_time.fn % period is
0, where period = intave * 104 (typically 624 frames).  Since CLCK.ind
with FN=0 satisfies this condition, a report is sent at the very
beginning of each clock epoch.

This was not a problem before commit fcfc4e83, because the first
CLCK.ind from the transciever was effectively a no-op: with
last_fn_timer.fn zero-initialised, the first indication at FN=0 yielded
elapsed_fn=0 (not > MAX_FN_SKEW), and the catch-up loop (while fn !=
last_fn_timer.fn) would not execute either.  Downlink scheduling only
started on the second CLCK.ind (at FN=102, which is > MAX_FN_SKEW),
and 102 % 624 != 0, so no RF RESOURCE INDICATION was triggered.

fcfc4e83 changed the logic so that Downlink scheduling now begins
immediately on the first CLCK.ind, via an unconditional call to
trx_setup_clock() -> bts_sched_fn(fn).  When fake_trx starts its frame
counter from FN=0, this immediately triggers l1sap_interf_meas_report()
because 0 % 624 == 0.  A second report follows ~2.88s later when the
periodic timer reaches FN=624, making the bootstrap logic
in ttcn3-bts-test unhappy.

Fix by shifting the trigger to (fn + 1) % period == 0, i.e. the report
fires at the last frame of each period rather than the first.  FN=0 now
yields (0+1) % 624 = 1 != 0, suppressing the spurious bootstrap report.
The periodic behaviour and report cadence are otherwise unchanged.

Change-Id: I6550178427b08e67c9763f0f37efff5b88960b1f
Related: fcfc4e83 ("osmo-bts-trx: fix spurious shutdown on first CLCK.ind from osmo-trx")
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28873 (Jun 29, 2026, 1:56:14 PM)

common: reset lchan meas state in gsm_ts_release()

lchan->meas (including interf_meas_num and num_ul_meas) is normally
only reset by lchan_meas_reset() called from rsl_tx_chan_act_ack() on
RSL CHANNEL ACTIVATION.  Idle logical channels are never RSL-activated,
so their measurement state is never reset via that path.

On an OML link re-establishment, osmo-bts does not exit: abis.c tears
down the signalling links, the bts_shutdown FSM powers down all TRXs,
and then waits for reconnect.  The gsm_bts/trx/ts/lchan structures
remain in memory, so stale interf_meas_num survives the reconnect.

This is why we're seeing these ERRORs while running ttcn3-bts-test:

(bts=0,trx=2,ts=4,ss=6) Not enough room to store interference report (0dBm)

Add a lchan_meas_reset() call to gsm_ts_release(), which is called
from nm_channel_fsm's NOTINSTALLED on_enter after the TRX is confirmed
closed.  This is exactly the right moment: the radio is fully stopped,
so no new samples arrive.

Change-Id: I18dc9d30417b0c5b2e579660d4a087d93445f956
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28872 (Jun 29, 2026, 1:56:10 PM)

common: stop buffering UL measurements when SACCH is deactivated

When the BSC sends RSL DEACT SACCH, the per-SACCH UL measurement drain
stops (it runs on SACCH timing), but the producer in lchan_new_ul_meas()
keeps appending the measurement contributions from every received
TCH/SDCCH burst.  After one SACCH period (104 frames) the 104-slot
uplink measurement buffer fills up, yielding a flood of:

  NOTICE measurement.c:336 no space for uplink measurement, num_ul_meas=104

Add a bool sacch_active flag to gsm_lchan, set to true in the common
l1sap_chan_act() and clear in l1sap_chan_deact_sacch().  Guard
lchan_new_ul_meas() with this flag so that measurements are silently
discarded while SACCH is inactive - there is nothing to drain the
buffer and no SACCH channel on which to report the results to the BSC.

Change-Id: I3943c788cab5d2411b06ac681d4d412852bac0a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28871 (Jun 29, 2026, 1:54:02 PM)

oml: validate Intave Parameter range in SET BTS ATTR

3GPP TS 52.021 §9.4.24 defines valid range for the Intave Parameter
as 1..31, matching the fixed size of the per-lchan interference sample
buffer (interf_meas_dbm[31] in lchan.h).  Previously any uint8_t value
was accepted without validation, meaning a buggy BSC could send
intave=0 (silently disabling interference reporting) or intave>31
(causing a buffer overflow in gsm_lchan_interf_meas_push()).

Let's guard against that by NACKing the SET BTS ATTR message with
cause=NM_NACK_PARAM_RANGE if the value is outside the valid range.

Change-Id: Id4d3353d4397aaa2517091b020d38ee15e084e2c
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28870 (Jun 29, 2026, 1:22:01 PM)

lint: ignore LINUX_VERSION_CODE

When running the linter against dahdi-linux.git or potentially other
repositories with out-of-tree linux kernel modules, it should not
complain about the LINUX_VERSION_CODE being used there:

> drivers/dahdi/dahdi-base.c:6397: WARNING:LINUX_VERSION_CODE:
> LINUX_VERSION_CODE should be avoided, code should be for the version to
> which it is merged

Change-Id: I82d64d43c04561b1643785cb71cfee92e513e560
Oliver Smith at

#28869 (Jun 29, 2026, 9:59:31 AM)

contrib/jenkins: run 'rebar3 fmt --check'

The pull request "v0.0.2" had a patch that formatted everything with
erlfmt. Let's run it in CI to keep the style consistent.

Related: https://github.com/onomondo/onomondo-eim/pull/10/commits/8bafdb3839d868d6bc18499617761d9acd73d2ad
Change-Id: I271c90dace6e7b6f052b38054815e6dfcbfa60f5
Oliver Smith at

#28868 (Jun 29, 2026, 9:59:29 AM)

src/utils.erl: format with erlfmt

Keep the file consistent with the rest of the codebase by running
'rebar3 fmt -w' on it.

Change-Id: I806c912a1bc82c26ecd23759a927f22328e743b9
Oliver Smith at

#28867 (Jun 29, 2026, 9:55:41 AM)

contrib/jenkins: run 'rebar3 fmt --check'

The pull request "v0.0.2" had a patch that formatted everything with
erlfmt. Let's run it in CI to keep the style consistent.

Related: https://github.com/onomondo/onomondo-eim/pull/10/commits/8bafdb3839d868d6bc18499617761d9acd73d2ad
Change-Id: I271c90dace6e7b6f052b38054815e6dfcbfa60f5
Oliver Smith at

#28866 (Jun 29, 2026, 9:53:16 AM)

contrib/jenkins: run 'rebar3 fmt --check'

The pull request "v0.0.2" had a patch that formatted everything with
erlfmt. Let's run it in CI to keep the style consistent.

Related: https://github.com/onomondo/onomondo-eim/pull/10/commits/8bafdb3839d868d6bc18499617761d9acd73d2ad
Change-Id: I271c90dace6e7b6f052b38054815e6dfcbfa60f5
Oliver Smith at

#28865 (Jun 29, 2026, 9:38:57 AM)

src/grd: use sys.exit

The exit function is a constant from the site module, which "should not
be used in programs". Replace it with sys.exit()

Related: https://docs.python.org/3/library/constants.html#constants-added-by-the-site-module
Change-Id: I95db013e36242d5126ce07b8a392e6dc0a0ecfdd
Oliver Smith at

#28864 (Jun 29, 2026, 9:38:54 AM)

src/grd: apply ruff formatter

The src/grd script is not part of the default "include" pattern as the
script does not end in ".py" (it used to be a shell script earlier). Add
it to the config explicitly and run "ruff format".

Change-Id: Id8da8e6b3325c8301276fd164ba218e8c5a95951
Oliver Smith at

#28863 (Jun 29, 2026, 9:38:50 AM)

src/grd: use origin url to get get host + project

For most projects we can get the gerrit host and project from the git
remote URL already. Do this when a git repository has no ".gitreview"
file so it works even if the file is not present.

Change-Id: Ib2b201e5238ba7036c6121e8875ee85c73da8751
Oliver Smith at

#28862 (Jun 29, 2026, 8:53:25 AM)

jobs/{master,gerrit}: eim,ipa: wipe-workspace

Set wipe-workspace for the onomondo-eim and onomondo-ipa jobs to true,
so previous failures cannot influence new jenkins job runs. E.g.
currently we have gerrit-onomondo-ipa-build failing with:

  + mkdir build
  mkdir: cannot create directory 'build': File exists

Most existing jobs call scripts/osmo-clean-workspace.sh from osmo-ci.git
at the beginning of their jenkins.sh instead of using wipe-workspace.
But this doesn't have any advantage here while making jenkins.sh more
complex. Let's use the built-in feature from jenkins here.

Change-Id: If4ef5ab804b05ad630cfa770741fe6053fdfb637
Oliver Smith at

#28861 (Jun 29, 2026, 8:37:55 AM)

scard: add comment about memory-leak in libpcsclite

As it seems, SCardReleaseContext does not free all of the memory
allocated by SCardEstablishContext. The probem has no real-world
impact, but still showas up in valgrind. Let's add a comment so
that we do not forget what causes the leak.

Related: SYS#8101
Change-Id: I5224f3824ce2ad33e678cd859ad28c47788dbb24
pmaier@sysmocom.de at

#28860 (Jun 29, 2026, 8:36:56 AM)

es10b_get_euicc_info: add explanatory comments regarding EUICCInfo2

onomondo-ipa has a built-in IoT eUICC emulation. This means that we
have to deal with two different EUICCInfo2 formats, which requires
additional logic in ipa_es10b_get_euicc_info_free to free the
allocated structs correctly. Since it is not immediately obvious
how the logic works, let's add some explanary comments to make it
obvious.

Related: SYS#8101
Change-Id: I282fa91a4099a771a353101b0ce17ae3daae9c42
pmaier@sysmocom.de at

#28859 (Jun 26, 2026, 3:42:58 PM)

Revert "bts: limit stderr logging to ERROR to avoid long write() to ext4 fs"

This reverts commit 3c798765f04dd7428c76e3c5cbf3f2ee27a0af4d.

Reducing logging verbosity did not help: we're still seeing the clock
skew errors and restarts.  This makes debugging harder, and is not
relevant anymore because we've switched to tmpfs [1].

Related: [1] docker-playground.git Id9a93f7149ef7e9bfde1f4fe3a8299ba46645d50
Change-Id: Id234394fda1ce752f93448e2fc03887a097f6b9d
Vadim Yanitskiy at

#28858 (Jun 26, 2026, 3:42:51 PM)

Revert "bts: limit stderr logging to NOTICE to avoid long write() to ext4 fs"

This reverts commit c3ab9ec33f37c6837fb8bcb0fa0bbd2e98781fb7.

Reducing logging verbosity did not help: we're still seeing the clock
skew errors and restarts.  This makes debugging harder, and is not
relevant anymore because we've switched to tmpfs [1].

Related: [1] docker-playground.git Id9a93f7149ef7e9bfde1f4fe3a8299ba46645d50
Change-Id: Ief6c3a6ca3053ccf745a186f7bb440e8540336f4
Vadim Yanitskiy at

#28857 (Jun 25, 2026, 10:07:32 PM)

saip/personalization: add MncLen configurable parameter

Add a new ConfigurableParameter that represents the MNC length
(2 or 3 digits) in EF.AD (Administrative Data).

Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3
Co-authored-by: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
Jenkins: skip-card-test
Vadim Yanitskiy at

#28856 (Jun 25, 2026, 9:58:07 PM)

saip/personalization: add MncLen configurable parameter

Add a new ConfigurableParameter that represents the MNC length
(2 or 3 digits) in EF.AD (Administrative Data).

Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3
Co-authored-by: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
Jenkins: skip-card-test
Vadim Yanitskiy at

#28855 (Jun 25, 2026, 7:48:26 PM)

pySim.log, pySim-shell: fix compatibility with cmd2 >= 3.0.0

Some Linux distributions (e.g. Arch Linux) already ship cmd2 3.x.x,
which removed the style()/Fg/Bg API in favor of stylize()/Color.

Add a version guard to select the right API at runtime.
Adjust the upper bound cap in requirements.txt and setup.py.

Change-Id: Ibf2ac7847933296fb06665c87f53ed6e1f315d27
Vadim Yanitskiy at

#28854 (Jun 25, 2026, 5:52:30 PM)

pySim-shell: drop backwards compat quirks for cmd2 < 2.6.2

Remove version guards for cmd2 < 2.0.0 and < 2.3.0, the Cmd2Compat
and Settable2Compat wrapper classes, and the old fg/bg color API -
none of these are needed since both requirements.txt and setup.py
already mandate cmd2 >= 2.6.2.

Change-Id: Ifd1c484ab66d74323d10e946347daa637cf6f5d8
Vadim Yanitskiy at

#28853 (Jun 25, 2026, 5:52:27 PM)

pySim.log, pySim-shell: fix compatibility with cmd2 >= 3.0.0

Some Linux distributions (e.g. Arch Linux) already ship cmd2 3.x.x,
which removed the style()/Fg/Bg API in favor of stylize()/Color.

Add a version guard to select the right API at runtime.
Adjust the upper bound cap in requirements.txt and setup.py.

Change-Id: Ibf2ac7847933296fb06665c87f53ed6e1f315d27
Vadim Yanitskiy at

#28852 (Jun 25, 2026, 5:52:24 PM)

setup.py: Align cmd2 minimum version with requirements.txt

As pointed out in the commit-log of Change-Id
I5186f242dbc1b770e3ab8cdca7f27d2a1029fff6 we had different minimum
versions for cmd2 in requirements.txt vs setup.py.  Let's align that.

Change-Id: I71cee0ec3ed2abec68ec567beaab13c868721dad
Vadim Yanitskiy at

#28851 (Jun 24, 2026, 9:28:32 AM)

esipa_asn1_handler: fix transactionId handling

The transactionId member is now called eimTransactionId. It is also
an optional member.

Change-Id: I1340e0c7aed091e8e5a5089ebd6e524512408cf7
Related: SYS#8100
pmaier@sysmocom.de at

#28850 (Jun 24, 2026, 9:28:30 AM)

rest_api_response_schema: add missing error codes

In SGP.32 V.1.2, new error codes were added to EnableProfileResult,
DisableProfileResult, DeleteProfileResult and AddEimResult

See also: SGP.32, section 2.11.2

Change-Id: I525ca9d3b7fb870405d374160272d8ec26c85880
Related: SYS#8100
pmaier@sysmocom.de at

#28849 (Jun 24, 2026, 9:28:27 AM)

esipa_asn1_handler: re-align to SGP.32 section Section 2.11.2 and Section 5.14.6

Section 2.11.2: eIM package result (EuiccPackageResult case) is now concatenated with PendingNotificationList instead of RetrieveNotificationsListResponse
Section 5.14.6: ESipa.ProvideEimPackageResult: Significant change in parameters

Change-Id: Ic0872edefc1844166943c60528557c6b7a6602ce
Related: SYS#8100
pmaier@sysmocom.de at

#28848 (Jun 24, 2026, 9:28:25 AM)

eim_cfg: set eimSupportedProtocol and indirectProfileDownload flags

The members eimSupportedProtocol and indirectProfileDownload were
added as optional members to EimConfigurationData with SGP.32 V.1.2.

Since our eIM implementation only supports eIM Package Retrieval via
HTTPs and the Indirect Profile Download procedure is the only Profile
Download procedure we currently support, the EimConfigurationData
should reflect those properties correctly.

(The EimConfigurationData is not announced actively by the eIM, but
this eIM implementation contains a generator to help with the encoding
of the EimConfigurationData that is programmed into the eUICC)

Change-Id: I4ce236fb1bfb8a3790191be95ab0958dce13a9d8
Related: SYS#8100
pmaier@sysmocom.de at

#28847 (Jun 24, 2026, 9:28:22 AM)

esipa_rest_utils: align IpaEuiccDataResponse to SGP.32 V.1.2

The ASN.1 struct IpaEuiccDataResponse has renamed the error code
member from ipaEuiccDataError to ipaEuiccDataErrorCode. The new
ipaEuiccDataErrorCode is a sequence that has an ipaEuiccDataErrorCode
member, which is the equivalent of the previously existing
ipaEuiccDataError member.

See also: SGP.32, section 2.11.2.2

Change-Id: Ie734a09ed4b0d57de30dc6fb377dfada79ea2ae4
Related: SYS#8100
pmaier@sysmocom.de at

#28846 (Jun 24, 2026, 9:28:19 AM)

esipa_rest_utils: re-align to SGP.32 Section 2.11.2

Section 2.11.2: rename EuiccPackageResultDataSigned.configureAutoEnableResult to EuiccPackageResultDataSigned.configureImmediateEnableResult

Change-Id: Ib4e6a4b4cb4d26a391346169b9047515496dd308
Related: SYS#8100
pmaier@sysmocom.de at

#28845 (Jun 24, 2026, 9:28:16 AM)

rest_api: move "required" member to the correct level

In some locations in the JSON schema files we find the "required"
member on the same lavel as the "properties" (likewise "items")
members. This is incorrect, the "required" member should always be
on the same level as the "properties" member

(At the moment the JSON schema files serve only documentation purposes,
they are not used to do any actual validation yet.)

Change-Id: I07d51d0e809a718144bd51a6540ab51187bb4daa
Related: SYS#8100
pmaier@sysmocom.de at

#28844 (Jun 24, 2026, 9:28:12 AM)

rest_api: revert json schema re-formatting

The JSON schema got reformatted in patch 78810e9d0e2c4fcfa0bff2e16aedd225c7145055,
however, the reformatted version now follows a scheme that is incompatible with
the emacs default settings. This makes it very hard to work with those files, so
let's revert this change.

Change-Id: I2361891875a8e190fff7003196c2df76fd877080
Related: SYS#8100
pmaier@sysmocom.de at

#28843 (Jun 24, 2026, 9:28:10 AM)

es9p_client: section 6.3.2.1, rename euiccCiPKIdToBeused to match SGP.32 V.1.2

Section 6.3.2.1: rename InitiateAuthenticationOkEsipa.euiccCiPKIdToBeused to InitiateAuthenticationOkEsipa.euiccCiPKIdentifierToBeUsed

Change-Id: I44c60a2f0d1129093ea67908d2eed167643a4a87
Related: SYS#8100
pmaier@sysmocom.de at

#28842 (Jun 24, 2026, 9:27:37 AM)

esipa_rest_utils: add support for PSMOs added in SGP.32 V.1.2

SGP.32 adds 3 additional PSMOs:
- setFallbackAttribute
- unsetFallbackAttribute
- setDefaultDpAddress

Change-Id: I03cdd70065a83dfc611d614cf32d817c13fad347
Related: SYS#8100
pmaier@sysmocom.de at

#28841 (Jun 24, 2026, 9:27:32 AM)

esipa_asn1_codec: add special handling for ProvideEimPackageResultResponse

In SGP.32 V.1.2 ProvideEimPackageResultResponse is defined as a CHOICE.
This means that this struct now also requires special handling.

Change-Id: I859a175cc28a18ea9334d9b2cf233294fdc95b76
Related: SYS#8100
pmaier@sysmocom.de at

#28840 (Jun 24, 2026, 8:29:19 AM)

es10b_get_euicc_info: add explanatory comments regarding EUICCInfo2

onomondo-ipa has a built-in IoT eUICC emulation. This means that we
have to deal with two different EUICCInfo2 formats, which requires
additional logic in ipa_es10b_get_euicc_info_free to free the
allocated structs correctly. Since it is not immediately obvious
how the logic works, let's add some explanary comments to make it
obvious.

Related: SYS#8101
Change-Id: I282fa91a4099a771a353101b0ce17ae3daae9c42
pmaier@sysmocom.de at

#28839 (Jun 24, 2026, 8:26:23 AM)

es10b_get_euicc_info: add explanatory comments regarding EUICCInfo2

onomondo-ipa has a built-in IoT eUICC emulation. This means that we
have to deal with two different EUICCInfo2 formats, which requires
additional logic in ipa_es10b_get_euicc_info_free to free the
allocated structs correctly. Since it is not immediately obvious
how the logic works, let's add some explanary comments to make it
obvious.

Related: SYS#8101
Change-Id: I282fa91a4099a771a353101b0ce17ae3daae9c42
pmaier@sysmocom.de at

#28838 (Jun 24, 2026, 8:26:19 AM)

scard: add comment about memory-leak in libpcsclite

As it seems, SCardReleaseContext does not free all of the memory
allocated by SCardEstablishContext. The probem has no real-world
impact, but still showas up in valgrind. Let's add a comment so
that we do not forget what causes the leak.

Related: SYS#8101
Change-Id: I5224f3824ce2ad33e678cd859ad28c47788dbb24
pmaier@sysmocom.de at

#28837 (Jun 24, 2026, 8:24:18 AM)

scard: add comment about memory-leak in libpcsclite

As it seems, SCardReleaseContext does not free all of the memory
allocated by SCardEstablishContext. The probem has no real-world
impact, but still showas up in valgrind. Let's add a comment so
that we do not forget what causes the leak.

Related: SYS#8101
Change-Id: I5224f3824ce2ad33e678cd859ad28c47788dbb24
pmaier@sysmocom.de at

#28836 (Jun 24, 2026, 8:23:46 AM)

es10b_get_euicc_info: add explanatory comments regarding EUICCInfo2

onomondo-ipa has a built-in IoT eUICC emulation. This means that we
have to deal with two different EUICCInfo2 formats, which requires
additional logic in ipa_es10b_get_euicc_info_free to free the
allocated structs correctly. Since it is not immediately obvious
how the logic works, let's add some explanary comments to make it
obvious.

Related: SYS#8101
Change-Id: I282fa91a4099a771a353101b0ce17ae3daae9c42
pmaier@sysmocom.de at

#28835 (Jun 24, 2026, 8:23:43 AM)

scard: add comment about memory-leak in libpcsclite

As it seems, SCardReleaseContext does not free all of the memory
allocated by SCardEstablishContext. The probem has no real-world
impact, but still showas up in valgrind. Let's add a comment so
that we do not forget what causes the leak.

Related: SYS#8101
Change-Id: I5224f3824ce2ad33e678cd859ad28c47788dbb24
pmaier@sysmocom.de at

#28834 (Jun 24, 2026, 8:22:11 AM)

es10b_get_euicc_info: add explanatory comments regarding EUICCInfo2

onomondo-ipa has a built-in IoT eUICC emulation. This means that we
have to deal with two different EUICCInfo2 formats, which requires
additional logic in ipa_es10b_get_euicc_info_free to free the
allocated structs correctly. Since it is not immediately obvious
how the logic works, let's add some explanary comments to make it
obvious.

Related: SYS#8101
Change-Id: I282fa91a4099a771a353101b0ce17ae3daae9c42
pmaier@sysmocom.de at

#28833 (Jun 24, 2026, 8:22:08 AM)

scard: add comment about memory-leak in libpcsclite

As it seems, SCardReleaseContext does not free all of the memory
allocated by SCardEstablishContext. The probem has no real-world
impact, but still showas up in valgrind. Let's add a comment so
that we do not forget what causes the leak.

Related: SYS#8101
Change-Id: I5224f3824ce2ad33e678cd859ad28c47788dbb24
pmaier@sysmocom.de at

#28832 (Jun 23, 2026, 10:46:23 PM)

stp: for TCAP loadshare: use NI == national

Use a non-zero NI. The TCAP tests don't check it
on the receive path, but the osmo-stp is checking
it if it matches the configuration.

Related: SYS#8061
Change-Id: I51ef302ad72ff3c434fddb39006ce50106a5918f
lynxis at

#28831 (Jun 23, 2026, 7:44:16 PM)

osmo-bts-trx: fix spurious clock skew shutdown after self-compensation

When the BTS runs ahead of the transceiver (elapsed_fn < 0),
trx_sched_clock() reschedules the timerfd to deliberately delay the
next FN.  osmo_timerfd_schedule() resets the timerfd and discards any
accumulated expirations, but last_fn_timer.tv was left pointing at
the previous callback.  The next trx_fn_timer_cb() then measures
elapsed_us all the way back to that previous callback - spanning the
deliberate delay (or any OS stall that preceded us) - and falsely
trips the "PC clock skew too high" check, shutting the BTS down
for no good reason.

Advance last_fn_timer.tv to the projected firing time of the
rescheduled timer so that the next callback measures roughly
one FN interval, as expected.

Change-Id: Icdb7db8abe70258ae008d9514b6608bd74bb2881
AI-Assisted: yes (Claude)
Related: OS#6794
Vadim Yanitskiy at

#28830 (Jun 23, 2026, 7:41:57 PM)

osmo-bts-trx: fix spurious shutdown on first CLCK.ind from osmo-trx

osmo-trx starts its frame counter from a random value rather than 0.
When the first CLCK.ind arrives, last_fn_timer and last_clk_ind are
still zero-initialised (set by trx_sched_clock_started()), so:

* compute_elapsed_fn(0, fn) wraps to a large negative for any fn
  greater than hyperframe/2 (1357824), satisfying elapsed_fn < 0;
* compute_elapsed_us({0,0}, &tv_now) returns the full CLOCK_MONOTONIC
  uptime (potentially days), satisfying the error_us threshold.

Together these trip the stale-clock shutdown introduced in the previous
commit (0199c108), even though the transceiver is perfectly healthy:

DL1C NOTICE scheduler_trx.c:490 GSM clock started, waiting for clock indications
DL1C FATAL scheduler_trx.c:589 Stale CLCK.ind: fn=1456348 is 250957770198 us behind
DOML NOTICE bts_shutdown_fsm.c:268 BTS_SHUTDOWN(bts0){NONE}: Shutting down BTS, exit 1, reason: TRX clock skew too high

Fix by adding clk_ind_received to osmo_trx_clock_state.  On the first
CLCK.ind after a (re)start, skip all elapsed-time checks and directly
bootstrap the scheduler from the reported FN.  The stale-clock
detection remains fully active for every subsequent indication,
where last_clk_ind holds a real baseline.

Change-Id: I25e76e02d29fd8f88130d15d0adfe8d90a017924
Fixes: 0199c108 ("osmo-bts-trx: shut down on stale clock indication from transceiver")
Related: OS#7021
Vadim Yanitskiy at

#28829 (Jun 23, 2026, 3:01:42 PM)

stp: tcap-loadshare: add TC_tcap_loadshare_m3ua_to_ipa_udts

If a TCAP message arrives which is:
* not a TCAP Begin or Abort (e.g. a TCAP Continue)
* not in the TCAP session cache/tracking
* not have a dTID for a registered TCAP Add Range

The tcap load-share will reject this message with a UDTS

Related: SYS#8061
Change-Id: I181b25aedfd70d156c08197d361560b6d055e65a
lynxis at

#28828 (Jun 23, 2026, 11:25:41 AM)

asn1/SGP32Definitions: apply workarounds

- Some ASN.1 structs from SGP.22 are re-defined under the same name by SGP.32.
  This leads to name clashes, which most ASN.1 compilers have problems with.
  Prefixing the re-defined struct in SGP.32 with "SGP32-" solves the problem.

- The erlang asn1ct ASN.1 compiler seems to misinterpret the ASN.1 spec when
  a context specific tag is used (redundently) on a child struct definition
  and in the parent definition at the same time. Removing te context specific
  tag on the child struct definition solves the problem.

Change-Id: Id90b005fc3c8c8f737b0c740d4c067f90842a1fe
Related: SYS#8100
pmaier@sysmocom.de at

#28827 (Jun 23, 2026, 11:25:37 AM)

asn1/SGP32Definitions: upgrade ASN.1 spec to V.1.2

This replaces the existing SGP.32 V.1.0.1 ASN.1 spec with the
unmodified, official SGP.32 V.1.2 spec.

Unfortunately V.1.2 is not backward compatible to V.1.0.1. This means
that the eIM application will still compile, but the result will be
non-functional. The incompatibility problems will be addressed in
the follow-up patches of this patchset.

Change-Id: Id4d217296f43846aa39f5dc7076465e2dab72a7c
Related: SYS#8100
pmaier@sysmocom.de at

#28826 (Jun 23, 2026, 11:14:32 AM)

contrib/jenkins: run 'rebar3 fmt --check'

The pull request "v0.0.2" had a patch that formatted everything with
erlfmt. Let's run it in CI to keep the style consistent.

Related: https://github.com/onomondo/onomondo-eim/pull/10/commits/8bafdb3839d868d6bc18499617761d9acd73d2ad
Change-Id: I271c90dace6e7b6f052b38054815e6dfcbfa60f5
Oliver Smith at

#28825 (Jun 23, 2026, 10:44:36 AM)

certificates: fix certificate location, make sure cert/key files are readable

The certificate and key files are placed in the config directory. This is
an unfortunate location, since it causes a lot of trouble when referencing
those files.

The erlang documentation suggests to place so called auxillary files in a
"priv" directory on the same level as the config directory. The path to
the priv directory can then be located using code:priv_dir.

see also: https://www.erlang.org/docs/26/design_principles/applications.html

Let's adopt this mechanism by adding utility functions that allow us to
resolve the file paths to files inside the priv directory. Let's also
automatically check if the referenced file is readable, so that we get
a proper error in the log in case a certificate or key file is missing

Change-Id: Ie09d746a6e28ac6fee3e00dfa32cb01f8a7b947e
Related: SYS#7093
pmaier@sysmocom.de at

#28824 (Jun 23, 2026, 10:38:56 AM)

esipa_rest_utils: fix searchCritera.profileClass type conversion

We currently use utils:hex_to_integer to convert the ProfileClass,
which is supposedly a string, to integer. However, hex_to_inteteger
does not exist and when looking into the related JSON schema
definition of we see that the profileClass member is already defined
as integer. This means that ProfileClass already arrives as integer
and can be used as it is. removing the hex_to_integer call solves
the problem.

Change-Id: I4bd223dbef00be9c800539b8d0dc9a84e3e93b73
pmaier@sysmocom.de at

#28823 (Jun 23, 2026, 9:09:33 AM)

jobs/master-builds: add onomondo-{eim,ipa}

Related: SYS#8103
Change-Id: I07f0cff5ce31e60135dff84554f21d8b404f7c72
Oliver Smith at

#28822 (Jun 23, 2026, 8:19:47 AM)

tls: fix broken certificate hostname verification

verify_cert_cb() retrieved the gnutls session pointer and passed it to
gnutls_certificate_verify_peers3() as the expected hostname.  But the
session pointer is set to the osmo_tls_session struct (it is needed by
cert_callback()), not a hostname string.  Hostname matching was
therefore performed against raw struct bytes, rendering verification
meaningless and potentially reading out of bounds, even when
"tls verify-cert" was enabled.

Store the configured hostname in struct osmo_tls_session and have
verify_cert_cb() read it from there.  Also drop the stray
gnutls_certificate_verify_peers3() call in the client setup: it ran
before any handshake (so there were no peer certificates yet) and its
result was ignored; the real verification happens via the registered
callback during the handshake.

Change-Id: If64950a698bfcfbf556a37ef1be3e68abc124384
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28821 (Jun 23, 2026, 8:19:45 AM)

server: fix NULL deref of file_hdr_msg when store is disabled

When a connection has storing disabled (no store), conn->file_hdr_msg
is never populated.  The previous link-header handling skipped the
first branch (gated on conn->store) and fell through to the comparison
branch, which dereferenced the still-NULL conn->file_hdr_msg, crashing
the server on the first PKT_LINK_HDR from such a client.

Gate the whole header tracking on conn->store and simply free the
message when not storing, since osmo_pcap_conn_restart_trace() already
no-ops in that case.

Change-Id: I419e1b66d07307c3e49294984887c153cd8494c3
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28820 (Jun 23, 2026, 8:18:42 AM)

server: vty: validate rotate-localtime modulus against the new interval

apply_rotate_localtime() computed the maximum allowed modulus from
pcap_server->rotate_localtime.intv, the currently-stored (old) interval,
rather than the intv argument being applied.  On first configuration the
stored interval is the default 0, so the switch hit the default case and
rejected an otherwise valid command; when changing intervals the modulus
was bounds-checked against the wrong interval.  Switch on intv instead.

Change-Id: I0b367d4e255db3208b41e12adec682026b99cc18
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28819 (Jun 23, 2026, 8:18:22 AM)

tls: do not treat GNUTLS_E_AGAIN/INTERRUPTED as fatal on read

osmo_tls_client_bfd_cb() treated any non-positive return from
gnutls_record_recv() as a fatal error and tore down the session.  On a
non-blocking socket gnutls_record_recv() can return GNUTLS_E_AGAIN or
GNUTLS_E_INTERRUPTED (both negative but non-fatal), which would drop
an otherwise healthy TLS session.  Handle them as retryable, mirroring
the existing logic in tls_write().

Change-Id: If2f842b202dd08c07dffe3770c51cf0ce886beee
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28818 (Jun 23, 2026, 8:18:12 AM)

client: honor IPv4 header length in GPRS filter

The GPRS-NS/BSSGP filter assumed a fixed 20-byte IPv4 header (IP_LEN)
when locating the UDP header and payload.  When the captured packet
carries IPv4 options (ip_hl > 5), udp_data/payload_data pointed into
the middle of the headers and check_gprs() parsed garbage, classifying
packets incorrectly.

Use the actual header length from ip_hl, reject malformed headers
(ip_hl < 5), and re-validate that the larger headers fit within the
captured length before computing the payload.

Change-Id: Iac1fa9cc2a3c06cbe19c3e7799a0b335f2e3dda9
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28817 (Jun 23, 2026, 7:00:35 AM)

utils: fix typos

Change-Id: Ib8ede7cbfed9198f59fe2899fe4b68eac5ac9a23
Oliver Smith at

#28816 (Jun 23, 2026, 7:00:05 AM)

utils/gsmtap-logsend: close infile before exit

Related: SYS#8093
Change-Id: I259cf951c52f7d859475f5f79c803692c29fbec3
Oliver Smith at

#28815 (Jun 22, 2026, 12:57:43 PM)

add comment about not updating existing key_usage_qualifier

Change-Id: Ie23ae5fde17be6b37746784bf1601b4d0874397a
Jenkins: skip-card-test
Vadim Yanitskiy at

#28814 (Jun 22, 2026, 12:57:41 PM)

saip: add numeric_base indicator to ConfigurableParameter

By default, numeric_base = None, to indicate that there are no explicit
limitations on the number space.

For parameters that are definitely decimal, set numeric_base = 10.
For definitely hexadecimal, set numeric_base = 16.

Do the same for ConfigurableParameter as well as ParamSource, so callers
can match them up: if a parameter is numeric_base = 10, then omit
sources that are numeric_base = 16, and vice versa.

Change-Id: Ib0977bbdd9a85167be7eb46dd331fedd529dae01
Jenkins: skip-card-test
Vadim Yanitskiy at

#28813 (Jun 22, 2026, 12:57:39 PM)

test_configurable_parameters.py: add tests for new parameters

For:
SmspTpScAddr
MilenageRotation
MilenageXoringConstants
TuakNrOfKeccak

Change-Id: Iecbea14fe31a9ee08d871dcde7f295d26d7bd001
Jenkins: skip-card-test
Vadim Yanitskiy at

#28812 (Jun 22, 2026, 12:57:36 PM)

saip SmspTpScAddr.get_values_from_pes: allow empty values

Change-Id: Ibbdd08f96160579238b50699091826883f2e9f5a
Jenkins: skip-card-test
Vadim Yanitskiy at

#28811 (Jun 22, 2026, 12:57:32 PM)

SmspTpScAddr: fix SMSP record length and alpha_id padding

apply_val() was re-encoding the SMSP with the minimum total_len of 28,
which produces a 28-byte body with no alpha_id field.  After a DER
round-trip, the profile machinery re-pads the body to the original
record length using the template's fill pattern, which may not be 0xFF.
Those non-0xFF fill bytes end up in the alpha_id area, and GSM 7-bit
decoding then fails with a KeyError when the modified profile is read
back.

Fix by:
- setting alpha_id = '' so the field is present but empty
- setting f_smsp.rec_len = 42 (28 fixed bytes + 14 bytes of alpha_id
  padding) so the re-encoded body carries 0xFF-padded alpha_id space
  and the efFileSize in the fileDescriptor stays consistent
- passing total_len=f_smsp.rec_len to encode_record_bin() so the
  alpha_id area is actually padded to that length

Change-Id: Ief6e02517f3e96158a2509d763b88aec4bd5a296
Jenkins: skip-card-test
Vadim Yanitskiy at

#28810 (Jun 22, 2026, 12:57:29 PM)

MncLen

Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3
Jenkins: skip-card-test
Vadim Yanitskiy at

#28809 (Jun 22, 2026, 12:03:42 PM)

gitignore: add build dir

Change-Id: Iea8f79b4094ed79f64b0ed6d6e34212ebaea0c43
Oliver Smith at

#28808 (Jun 22, 2026, 12:03:39 PM)

contrib/jenkins: build with -Werror

Now that all warnings are fixed, let's build with Werror in CI.

Change-Id: I8a8a7bc8a10e8d86a09fbd289b00641c19c3be6e
Oliver Smith at

#28807 (Jun 22, 2026, 12:03:35 PM)

activation_code: fix missing const for item_end

Fix for:
  …/src/ipa/libipa/activation_code.c: In function ‘ipa_activation_code_parse’:
  …/src/ipa/libipa/activation_code.c:62:26: error: assignment discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
     62 |                 item_end = strchr(item + 1, '$');
        |                          ^

Change-Id: Idcdd06f57da0e7c05ea184c56cadfc6de85514e6
Oliver Smith at

#28806 (Jun 22, 2026, 12:03:32 PM)

esipa: fix printf fmt str for ssize_t

Fix for:
  In file included from …/src/ipa/libipa/esipa.c:14:
  …/src/ipa/libipa/esipa.c: In function ‘ipa_esipa_msg_to_eim_enc’:
  …/src/ipa/libipa/esipa.h:16:33: error: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘ssize_t’ {aka ‘long int’} [-Werror=form
  at=]
     16 |         IPA_LOGP(SESIPA, level, "%s: " fmt, func, ## args)
        |                                 ^~~~~~
  …/include/onomondo/ipa/log.h:18:53: note: in definition of macro ‘IPA_LOGP’
     18 |         ipa_logp(subsys, level, __FILE__, __LINE__, fmt, ## args)
        |                                                     ^~~
  …/src/ipa/libipa/esipa.c:129:17: note: in expansion of macro ‘IPA_LOGP_ESIPA’
    129 |                 IPA_LOGP_ESIPA(function_name, LERROR, "cannot encode eIM request! rc = %d\n", rc.encoded);
        |                 ^~~~~~~~~~~~~~

Change-Id: I5b210ae5acff362cf845f6a37073d2bffe69c76e
Oliver Smith at

#28805 (Jun 22, 2026, 12:03:28 PM)

utils: ignore Waddress in IPA_STR_FROM_ASN

When building with -Werror, GCC complains about this assert in the macro:

  #define IPA_STR_FROM_ASN(asn1_obj) ({ \
  char *__str; \
  assert(asn1_obj); \    <----------------------
  __str = IPA_ALLOC_N((asn1_obj)->size + 1); \
  assert(__str); \
  memcpy(__str, (asn1_obj)->buf, (asn1_obj)->size); \
  __str[(asn1_obj)->size] = '\0'; \
  __str; \
  })

For example:

  …/src/ipa/libipa/es10b_get_eim_cfg_data.c:48:21: error: the comparison will always evaluate as ‘true’ for the address of ‘eimId’ will never be NULL [-Werror=address]
     48 |                     IPA_STR_FROM_ASN(&res->res->eimConfigurationDataList.list.array[i]->eimId);

Add pragmas to ignore the error, so it can still assert if somebody
should pass NULL to the macro.

Change-Id: Ia2ef30880dd3e5b2ab90eedd0046a95a22614a81
Oliver Smith at

#28804 (Jun 22, 2026, 12:03:25 PM)

contrib/jenkins: new script

Add a script for build verifications on https://jenkins.osmocom.org.

Related: SYS#8103
Change-Id: I0305c3196896667f4963853099d0767e0acbdb30
Oliver Smith at

#28803 (Jun 22, 2026, 10:53:25 AM)

jobs/gerrit-verifications: add onomondo-{eim,ipa}

Related: SYS#8103
Change-Id: Ib07ed316d80cbb857c34aede03e3d4468c3be578
Oliver Smith at

#28802 (Jun 22, 2026, 10:50:58 AM)

esipa: fix printf fmt str for ssize_t

Fix for:
  In file included from …/src/ipa/libipa/esipa.c:14:
  …/src/ipa/libipa/esipa.c: In function ‘ipa_esipa_msg_to_eim_enc’:
  …/src/ipa/libipa/esipa.h:16:33: error: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘ssize_t’ {aka ‘long int’} [-Werror=form
  at=]
     16 |         IPA_LOGP(SESIPA, level, "%s: " fmt, func, ## args)
        |                                 ^~~~~~
  …/include/onomondo/ipa/log.h:18:53: note: in definition of macro ‘IPA_LOGP’
     18 |         ipa_logp(subsys, level, __FILE__, __LINE__, fmt, ## args)
        |                                                     ^~~
  …/src/ipa/libipa/esipa.c:129:17: note: in expansion of macro ‘IPA_LOGP_ESIPA’
    129 |                 IPA_LOGP_ESIPA(function_name, LERROR, "cannot encode eIM request! rc = %d\n", rc.encoded);
        |                 ^~~~~~~~~~~~~~

Change-Id: I5b210ae5acff362cf845f6a37073d2bffe69c76e
Oliver Smith at

#28801 (Jun 22, 2026, 10:50:55 AM)

utils: ignore Waddress in IPA_STR_FROM_ASN

When building with -Werror, GCC complains about this assert in the macro:

  #define IPA_STR_FROM_ASN(asn1_obj) ({ \
  char *__str; \
  assert(asn1_obj); \    <-----------------------------------------------
  __str = IPA_ALLOC_N((asn1_obj)->size + 1); \
  assert(__str); \
  memcpy(__str, (asn1_obj)->buf, (asn1_obj)->size); \
  __str[(asn1_obj)->size] = '\0'; \
  __str; \
  })

For example:

  …/src/ipa/libipa/es10b_get_eim_cfg_data.c:48:21: error: the comparison will always evaluate as ‘true’ for the address of ‘eimId’ will never be NULL [-Werror=address]
     48 |                     IPA_STR_FROM_ASN(&res->res->eimConfigurationDataList.list.array[i]->eimId);

Add pragmas to ignore the error, so it can still assert if somebody
should pass NULL to the macro.

Change-Id: Ia2ef30880dd3e5b2ab90eedd0046a95a22614a81
Oliver Smith at

#28800 (Jun 22, 2026, 10:50:53 AM)

contrib/jenkins: build with -Werror

Now that all warnings are fixed, let's build with Werror in CI.

Change-Id: I8a8a7bc8a10e8d86a09fbd289b00641c19c3be6e
Oliver Smith at

#28799 (Jun 22, 2026, 10:50:47 AM)

gitignore: add build dir

Change-Id: Iea8f79b4094ed79f64b0ed6d6e34212ebaea0c43
Oliver Smith at

#28798 (Jun 22, 2026, 10:50:45 AM)

activation_code: fix missing const for item_end

Fix for:
  …/src/ipa/libipa/activation_code.c: In function ‘ipa_activation_code_parse’:
  …/src/ipa/libipa/activation_code.c:62:26: error: assignment discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
     62 |                 item_end = strchr(item + 1, '$');
        |                          ^

Change-Id: Idcdd06f57da0e7c05ea184c56cadfc6de85514e6
Oliver Smith at

#28797 (Jun 22, 2026, 10:13:35 AM)

contrib/jenkins: new script

Add a script for build verifications on https://jenkins.osmocom.org.

Related: SYS#8103
Change-Id: I0305c3196896667f4963853099d0767e0acbdb30
Oliver Smith at

#28796 (Jun 22, 2026, 10:00:50 AM)

contrib/jenkins: new script

Add a script for build verifications on https://jenkins.osmocom.org.

Related: SYS#8103
Change-Id: Id5f282fd1e3403be3b5d2fcb962c2dda62bae905
Oliver Smith at

#28795 (Jun 22, 2026, 8:34:42 AM)

CCID: Check if reader times out while expecting procedure byte

A case 3 APDU is sent toward the reader. The reader expects a procedure
byte or a status word. If none of these are sent by the SIM the reader
must timeout and send an error message back to the host.

Change-Id: Iacd6aacaf8220e69b9b7038e354d54c788d1eb05
Andreas Eversberg at

#28794 (Jun 22, 2026, 8:34:37 AM)

CCID: Send procedure byte, when not expected

A case 1 APDU does not request any data from SIM to return. The SIM will
only return a status byte with no procedure byte in advance.

The test sends a procedure byte in advance of the two status bytes
towards the reader. The reader expects SW1 instead of the status byte,
so that it returns it as SW1.

Change-Id: Icffd48d99f0eb48e0898efb027854eba8c22f4a4
Andreas Eversberg at

#28793 (Jun 22, 2026, 8:34:31 AM)

CCID: Check if reader handles Abort correctly

This test fails with osmo-ccid-firmware, because it is not yet
implemented.

Change-Id: Iebe97e73497b8468ebf08faf2c4db700fc76997f
Andreas Eversberg at

#28792 (Jun 22, 2026, 8:34:24 AM)

CCID: Check if reader times out after first status word

A case 1 APDU is sent towards the reader. The reader expects two status
words. If only the first word is sent by the SIM, the reader must
timeout and send an error message back to the host.

Change-Id: Ic5b892e356c13808555d75746c48c6d8c96ec462
Andreas Eversberg at

#28791 (Jun 22, 2026, 8:34:18 AM)

CCID: Send a wrong procedure byte towards the reader

A case 3 request is send and a response with data is expected, but the
first byte replied by the sim is not a procedure byte, nor a valid
status byte.

This text expects the reader to return an error that states an incorrect
received procedure byte.

Change-Id: Iaa0bd8845b3408fba309874fe41c855d8e7efccc
Andreas Eversberg at

#28790 (Jun 20, 2026, 11:02:34 PM)

server: vty: fix docs for cfg_server_rotate_localtime[_mod_n]

Change-Id: I6fd1d081bba035fbd9d72a1705ab58194edf274e
Fixes: 18747641 ("pcap-server: Make rotate-localtime feature configurable through VTY")
Vadim Yanitskiy at

#28789 (Jun 20, 2026, 11:02:31 PM)

vty: clamp configured snaplen to the wire-framing limit

osmo-pcap carries each captured packet in a frame whose length field
(struct osmo_pcap_data.len) is a uint16_t, so any snaplen above ~64 KiB
cannot be transported and is silently clamped by the server when sizing
its receive buffer (calc_data_max_len() caps at UINT16_MAX). The VTY,
however, advertised libpcap's MAXIMUM_SNAPLEN (262144), misleading users
into configuring values that never take effect.

Introduce OSMO_PCAP_MAX_SNAPLEN (65535) and, in both the client "pcap
snaplen" and server "max-snaplen" handlers, warn and cap the value to it
when a larger one is given. The command syntax keeps the <1-262144>
range for backwards compatibility so existing configs still parse; the
help text now documents the effective 64 KiB limit.

Change-Id: Ia56cad48e8cefe8ae103f2f7d2e037bf28438b71
AI-Assisted: yes (Claude)
Related: 6d2f7c52 ("server: Limit rx buffer size to UINT16_MAX")
Related: SYS#8099
Vadim Yanitskiy at

#28788 (Jun 20, 2026, 11:01:59 PM)

doc: clarify 'pcap snaplen' / 'max-snaplen'

Change-Id: Ic2c82173c12814d61f0ee9f7454b9e5dcb0c13f4
Related: SYS#8099
Vadim Yanitskiy at

#28787 (Jun 20, 2026, 9:06:02 PM)

tls: fix broken certificate hostname verification

verify_cert_cb() retrieved the gnutls session pointer and passed it to
gnutls_certificate_verify_peers3() as the expected hostname.  But the
session pointer is set to the osmo_tls_session struct (it is needed by
cert_callback()), not a hostname string.  Hostname matching was
therefore performed against raw struct bytes, rendering verification
meaningless and potentially reading out of bounds, even when
"tls verify-cert" was enabled.

Store the configured hostname in struct osmo_tls_session and have
verify_cert_cb() read it from there.  Also drop the stray
gnutls_certificate_verify_peers3() call in the client setup: it ran
before any handshake (so there were no peer certificates yet) and its
result was ignored; the real verification happens via the registered
callback during the handshake.

Change-Id: If64950a698bfcfbf556a37ef1be3e68abc124384
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28786 (Jun 20, 2026, 8:58:09 PM)

tls: fix broken certificate hostname verification

verify_cert_cb() retrieved the gnutls session pointer and passed it to
gnutls_certificate_verify_peers3() as the expected hostname.  But the
session pointer is set to the osmo_tls_session struct (it is needed by
cert_callback()), not a hostname string.  Hostname matching was
therefore performed against raw struct bytes, rendering verification
meaningless and potentially reading out of bounds, even when
"tls verify-cert" was enabled.

Store the configured hostname in struct osmo_tls_session and have
verify_cert_cb() read it from there.  Also drop the stray
gnutls_certificate_verify_peers3() call in the client setup: it ran
before any handshake (so there were no peer certificates yet) and its
result was ignored; the real verification happens via the registered
callback during the handshake.

Change-Id: If64950a698bfcfbf556a37ef1be3e68abc124384
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28785 (Jun 20, 2026, 8:58:04 PM)

server: fix NULL deref of file_hdr_msg when store is disabled

When a connection has storing disabled (no store), conn->file_hdr_msg
is never populated.  The previous link-header handling skipped the
first branch (gated on conn->store) and fell through to the comparison
branch, which dereferenced the still-NULL conn->file_hdr_msg, crashing
the server on the first PKT_LINK_HDR from such a client.

Gate the whole header tracking on conn->store and simply free the
message when not storing, since osmo_pcap_conn_restart_trace() already
no-ops in that case.

Change-Id: I419e1b66d07307c3e49294984887c153cd8494c3
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28784 (Jun 20, 2026, 8:57:59 PM)

server: fix zmq message leak on send failure

zmq_msg_send() only transfers ownership of the message to ZeroMQ on
success.  On failure the caller retains ownership, so the previously
init'd zmq_msg_t was leaked on every failed publish.  Close it
explicitly on the error path.

Change-Id: I501b1bf55bede4e69fa5d9b3f38d87341482ff49
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28783 (Jun 20, 2026, 8:57:56 PM)

server: fix msgb leak on duplicate link header

rx_link_hdr() takes ownership of msg on success (rx_link() only frees
it on failure).  Both branches that call update_conn_file_hdr_msg()
free msg, but when an identical link header was already stored neither
branch ran and msg was leaked.

This happens on every duplicate PKT_LINK_HDR, e.g. a client that
periodically resends its header.  Free msg explicitly in that case.

Change-Id: I79344fe942342f2a736878142b3cf036fc982eef
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28782 (Jun 20, 2026, 8:57:51 PM)

client: vty: do not print NULL tls hostname

conn->tls_hostname defaults to NULL and can be cleared via "no tls
hostname".  Writing it unconditionally emitted a "tls hostname (null)"
line, producing a config that does not re-parse.  Guard it like the
other optional tls fields.

Change-Id: I5b920337409d8c9fa1edb8d47177882cf0a6c4e7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28781 (Jun 20, 2026, 8:57:46 PM)

server: do not abort process on short conn message

conn_read_cb() used OSMO_ASSERT() to check that the received
message holds at least a full osmo_pcap_data header.  Although
conn_segmentation_cb2() should only ever hand up complete frames,
asserting on a length derived from network input means a framing
anomaly would abort the entire server (taking down all other clients'
captures).  Close the offending connection gracefully instead,
consistent with the other error paths in this function.

Change-Id: Ia102ff918ef8152d212e10a860f5dc70efec880b
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28780 (Jun 20, 2026, 8:57:43 PM)

client: honor IPv4 header length in GPRS filter

The GPRS-NS/BSSGP filter assumed a fixed 20-byte IPv4 header (IP_LEN)
when locating the UDP header and payload.  When the captured packet
carries IPv4 options (ip_hl > 5), udp_data/payload_data pointed into
the middle of the headers and check_gprs() parsed garbage, classifying
packets incorrectly.

Use the actual header length from ip_hl, reject malformed headers
(ip_hl < 5), and re-validate that the larger headers fit within the
captured length before computing the payload.

Change-Id: Iac1fa9cc2a3c06cbe19c3e7799a0b335f2e3dda9
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28779 (Jun 20, 2026, 8:57:37 PM)

client: fix off-by-one in wrapped pcap stats counter

When a libpcap stats counter (ps_recv/ps_drop/ps_ifdrop) wraps around
UINT_MAX, get_psbl_wrapped_ctr() computed the delta as
(UINT_MAX - old_val) + new_val, omitting the single increment that
takes the counter from UINT_MAX through zero.  Add the missing +1 so
the reported delta matches the real number of increments.

Change-Id: I66581910dbd1e955831a6ff913042059ad4994a7
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28778 (Jun 20, 2026, 8:57:29 PM)

tls: do not treat GNUTLS_E_AGAIN/INTERRUPTED as fatal on read

osmo_tls_client_bfd_cb() treated any non-positive return from
gnutls_record_recv() as a fatal error and tore down the session.  On a
non-blocking socket gnutls_record_recv() can return GNUTLS_E_AGAIN or
GNUTLS_E_INTERRUPTED (both negative but non-fatal), which would drop
an otherwise healthy TLS session.  Handle them as retryable, mirroring
the existing logic in tls_write().

Change-Id: If2f842b202dd08c07dffe3770c51cf0ce886beee
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28777 (Jun 20, 2026, 8:57:13 PM)

server: vty: validate rotate-localtime modulus against the new interval

apply_rotate_localtime() computed the maximum allowed modulus from
pcap_server->rotate_localtime.intv, the currently-stored (old) interval,
rather than the intv argument being applied.  On first configuration the
stored interval is the default 0, so the switch hit the default case and
rejected an otherwise valid command; when changing intervals the modulus
was bounds-checked against the wrong interval.  Switch on intv instead.

Change-Id: I0b367d4e255db3208b41e12adec682026b99cc18
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28776 (Jun 20, 2026, 8:55:31 PM)

client: Fix 32-bit overflow when computing pcapng EPB timestamp

tv_sec * 1000 * 1000 was evaluated in int arithmetic.  Where time_t /
tv_sec is 32-bit, this overflows for any tv_sec > ~2147, corrupting
the 64-bit timestamp_usec well before the year 2038.  Cast tv_sec to
uint64_t before the multiplication so the whole expression
is computed in 64 bits.

Change-Id: I20d3282b8cba1675ce2d0860e66027e5ee8245ef
AI-Assisted: yes (Claude)
Vadim Yanitskiy at

#28775 (Jun 20, 2026, 8:50:03 PM)

saip/param_source: try to not repeat random values

Change-Id: I4fa743ef5677580f94b9df16a5051d1d178edeb0
Jenkins: skip-card-test
Vadim Yanitskiy at

#28774 (Jun 20, 2026, 8:49:58 PM)

personalization: generate sdkey classes from a list

Change-Id: Ic92ddea6e1fad8167ea75baf78ffc3eb419838c4
Jenkins: skip-card-test
Vadim Yanitskiy at

#28773 (Jun 20, 2026, 8:49:52 PM)

ConfigurableParameter: do not magically overwrite the 'name' attribute

The ClassVarMeta metaclass used to derive each ConfigurableParameter's
'name' attribute automatically from the Python class name (via
camel_to_snake()).  Stop doing this, for three reasons:

1) Python class names follow constraints that do not fit the naming
   commonly used in CSV files.  For example, a name like
   "5GS-SUCI-CalcInfo" starts with a digit and contains dashes,
   neither of which is permissible in a class name.

2) Python class names live in their own namespace, distinct from the
   one used to present eSIM parameters to end users.  Deriving the UI
   name from the class name couples these two namespaces together.

   Taken together, (1) and (2) mean that automatic naming both imposes
   class-name constraints on the user-visible names and merges the
   internal Python namespace with the publicly shown one - a layer
   violation from the perspective of UI design.

3) Overriding 'name' from __new__() makes manual naming impossible: a
   subclass that sets 'name = "bar"' as a class attribute would still
   end up with the value computed by the metaclass, which is
   surprising and hard to track down:

       class MySuper(metaclass=...):  # __new__ sets name = 'foo'
           ...
       class MySub(MySuper):
           name = 'bar'
       print(MySub().name)  # 'foo', not 'bar' as one would expect

Change-Id: I6f631444c6addeb7ccc5f6c55b9be3dc83409169
Jenkins: skip-card-test
Vadim Yanitskiy at

#28772 (Jun 20, 2026, 8:49:48 PM)

saip: add numeric_base indicator to ConfigurableParameter

By default, numeric_base = None, to indicate that there are no explicit
limitations on the number space.

For parameters that are definitely decimal, set numeric_base = 10.
For definitely hexadecimal, set numeric_base = 16.

Do the same for ConfigurableParameter as well as ParamSource, so callers
can match them up: if a parameter is numeric_base = 10, then omit
sources that are numeric_base = 16, and vice versa.

Change-Id: Ib0977bbdd9a85167be7eb46dd331fedd529dae01
Jenkins: skip-card-test
Vadim Yanitskiy at

#28771 (Jun 20, 2026, 8:49:45 PM)

add comment about not updating existing key_usage_qualifier

Change-Id: Ie23ae5fde17be6b37746784bf1601b4d0874397a
Jenkins: skip-card-test
Vadim Yanitskiy at

#28770 (Jun 20, 2026, 8:49:42 PM)

add test_param_src.py

Change-Id: I03087b84030fddae98b965e0075d44e04ec6ba5c
Jenkins: skip-card-test
Vadim Yanitskiy at

#28769 (Jun 20, 2026, 8:49:39 PM)

personalization.ConfigurableParameter: fix BytesIO() input

Change-Id: I0ad160eef9015e76eef10baee7c6b606fe249123
Jenkins: skip-card-test
Vadim Yanitskiy at

#28768 (Jun 20, 2026, 8:49:35 PM)

ConfigurableParameter: safer val length check

validate_val() calls len() to check the value against allow_len,
min_len and max_len. len() requires the object to have a __len__()
method, which integers do not — calling len() on an int raises
TypeError.

Fix this by checking for __len__ first: if present, use len(val) as
usual; otherwise fall back to len(str(val)), which gives the number
of decimal digits for integer values.

Change-Id: Ibe91722ed1477b00d20ef5e4e7abd9068ff2f3e4
Jenkins: skip-card-test
Vadim Yanitskiy at

#28767 (Jun 20, 2026, 8:49:31 PM)

UppAudit: better indicate exception cause

Change-Id: I4d986b89a473a5b12ed56b4710263b034876a33e
Jenkins: skip-card-test
Vadim Yanitskiy at

#28766 (Jun 20, 2026, 8:49:28 PM)

test_configurable_parameters.py: add tests for new parameters

For:
SmspTpScAddr
MilenageRotation
MilenageXoringConstants
TuakNrOfKeccak

Change-Id: Iecbea14fe31a9ee08d871dcde7f295d26d7bd001
Jenkins: skip-card-test
Vadim Yanitskiy at

#28765 (Jun 20, 2026, 8:49:23 PM)

MncLen

Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3
Jenkins: skip-card-test
Vadim Yanitskiy at

#28764 (Jun 20, 2026, 8:49:17 PM)

param_source: use secrets.SystemRandom as secure random nr source

secrets.SystemRandom is defined as the most secure random source
available on the given operating system.

Change-Id: I8049cd1292674b3ced82b0926569128535af6efe
Jenkins: skip-card-test
Vadim Yanitskiy at

#28763 (Jun 20, 2026, 8:49:14 PM)

param_source: use random.SystemRandom as random nr source

Python's random module uses a PRNG (Mersenne Twister) which is
utterly insecure for key generation - it was so far only used for
testing.  Replace it with random.SystemRandom(), which draws from
/dev/urandom and is suitable for generating cryptographic key material.

Change-Id: I6de38c14ac6dd55bc84d53974192509c18d02bfa
Jenkins: skip-card-test
Vadim Yanitskiy at

#28762 (Jun 20, 2026, 8:49:08 PM)

add test_configurable_parameters.py

Add ConfigurableParameterTest, which applies each parameter to a real
UPP DER template and reads it back, comparing results against a stored
expected-output snapshot (xo/test_configurable_parameters).

Add TestValidateVal covering validate_val() for Iccid, Imsi, Pin1, Puk1
and K, testing both valid inputs and invalid ones expected to raise
ValueError.

Add TestEnumParam covering the EnumParam methods (validate_val,
map_name_to_val, map_val_to_name, name_normalize, clean_name_str) using
AlgorithmID as the concrete subclass, including fuzzy name matching.

Also add get_value_from_pes() to ConfigurableParameter as a convenience
wrapper around get_values_from_pes() that asserts all returned values
are identical and returns the single result.

Change-Id: Ia55f0d11f8197ca15a948a83a34b3488acf1a0b4
Co-authored-by: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
Jenkins: skip-card-test
Vadim Yanitskiy at

#28761 (Jun 20, 2026, 8:49:01 PM)

param_source: allow plugging a random implementation (for testing)

Change-Id: Idce2b18af70c17844d6f09f7704efc869456ac39
Jenkins: skip-card-test
Vadim Yanitskiy at

#28760 (Jun 20, 2026, 8:48:55 PM)

personalization: add int as input type for BinaryParameter

Change-Id: I31d8142cb0847a8b291f8dc614d57cb4734f0190
Jenkins: skip-card-test
Vadim Yanitskiy at

#28759 (Jun 20, 2026, 8:48:45 PM)

personalization: fix EF_SMSP length, alpha_id padding

The efFileSize needs to be updated and the alpha_id needs to be != None.

Change-Id: Ief6e02517f3e96158a2509d763b88aec4bd5a296
Jenkins: skip-card-test
Vadim Yanitskiy at

#28758 (Jun 20, 2026, 8:48:37 PM)

saip SmspTpScAddr.get_values_from_pes: allow empty values

Change-Id: Ibbdd08f96160579238b50699091826883f2e9f5a
Jenkins: skip-card-test
Vadim Yanitskiy at

#28757 (Jun 20, 2026, 7:12:18 AM)

struct gsm_bts: drop unused ms_max_power

Change-Id: I0b02015db8b8e670eaff40c578f0474d9be9bb45
Vadim Yanitskiy at

#28756 (Jun 20, 2026, 7:12:15 AM)

common: track whether gsm_time has been initialized

l1sap_info_time_ind() used 'bts->gsm_time.fn != 0' as a proxy for
"we have a previous frame number to diff against".  This is unreliable:
Fn=0 is a _valid_ frame number, recurring on every hyperframe wrap.
If gsm_time.fn happened to be 0 and the next time indication jumped
forward by more than one frame, the real gap was silently swallowed.

It also gave no clean way to suppress the bogus "Invalid condition
detected: Frame difference is ..." message that appears when the PHY
(re)starts its TDMA frame number (e.g. from 0) on bring-up.

Introduce an explicit 'bts->gsm_time_valid' flag instead:

* l1sap_info_time_ind() treats the first indication of an epoch as
  having no gap (frames_expired = 0): no warning, no RACH-slot
  accounting;
* the flag is cleared in st_op_disabled_notinstalled_on_enter(), so
  each BTS bring-up starts a fresh clock epoch regardless of which
  FN the PHY reports first.

Change-Id: I7022b0ad084a0c224f7e8c04aca0648915b1a1c6
AI-Assisted: yes (Claude)
Related: OS#7020
Vadim Yanitskiy at

#28755 (Jun 20, 2026, 7:12:11 AM)

tests/meas: remove unused 'delta'

gcc 16.1.1 emits a -Wunused-but-set-variable warning.

Change-Id: I2540d701743caefb4bf54bb5b4ebe683d3257071
Vadim Yanitskiy at

#28754 (Jun 20, 2026, 7:07:18 AM)

osmo-bts-trx: fix spurious clock skew shutdown after self-compensation

When the BTS runs ahead of the transceiver (elapsed_fn < 0),
trx_sched_clock() reschedules the timerfd to deliberately delay the
next FN.  osmo_timerfd_schedule() resets the timerfd and discards any
accumulated expirations, but last_fn_timer.tv was left pointing at
the previous callback.  The next trx_fn_timer_cb() then measures
elapsed_us all the way back to that previous callback - spanning the
deliberate delay (or any OS stall that preceded us) - and falsely
trips the "PC clock skew too high" check, shutting the BTS down
for no good reason.

Advance last_fn_timer.tv to the projected firing time of the
rescheduled timer so that the next callback measures roughly
one FN interval, as expected.

Change-Id: Icdb7db8abe70258ae008d9514b6608bd74bb2881
AI-Assisted: yes (Claude)
Related: OS#6794
Vadim Yanitskiy at

#28753 (Jun 20, 2026, 7:07:12 AM)

osmo-bts-trx: shut down on stale clock indication from transceiver

We expect the transceiver to be a reliable, monotonic clock source.
If it reports an FN far behind our local timer (elapsed_fn < 0) while
far more wall-clock time elapsed than its FN advance accounts for,
its clock has likely stalled and the indication carries a stale frame
number.  Acting on it drags the scheduler backwards and re-transmits
already-sent TDMA frames, corrupting lchan-internal state(s).

Detect this and shut down the process, same rationale as the existing
"PC clock skew too high" check in trx_fn_timer_cb().

Change-Id: If787ab7ed70aa2dcb0389ceb58620c2302c3431a
AI-Assisted: yes (Claude)
Related: OS#7020, OS#6794
Vadim Yanitskiy at

#28752 (Jun 18, 2026, 12:17:26 PM)

CCID: Check if reader sends request TPDU with maximum size

The maximum size of a request TPDU can have 5 bytes header and 255 bytes
data. It is expected that the reader transmits all bytes to SIM without
failure.

Change-Id: I7c1cb52b578c19d6c0ec1493e45f6ed9c43735b4
Andreas Eversberg at

#28751 (Jun 18, 2026, 12:17:22 PM)

CCID: Check if reader times out while expecting status words

A case 1 APDU is sent toward the reader. The reader expects two status
words. If none of these are sent by the SIM the reader must timeout and
send an error message back to the host.

Change-Id: I054b56a9e2f10e5b984ad0398efb4be5696ce16c
Andreas Eversberg at

#28750 (Jun 18, 2026, 12:17:18 PM)

CCID: Check if reader handles Abort correctly

This test fails with osmo-ccid-firmware, because it is not yet
implemented.

Change-Id: Iebe97e73497b8468ebf08faf2c4db700fc76997f
Andreas Eversberg at

#28749 (Jun 18, 2026, 12:17:14 PM)

SIMTRACE: Increase USB receive buffer size

The maximum SIM request data can be 255 bytes. Additionally, the
SIMtrace PDU header is 14 bytes. So increase the buffer to 269 bytes.

Change-Id: I05261b4a754b4892955d0b4e426bd32be261efa7
Andreas Eversberg at

#28748 (Jun 18, 2026, 12:17:10 PM)

CCID: Check if reader times out while expecting procedure byte

A case 3 APDU is sent toward the reader. The reader expects a procedure
byte or a status word. If none of these are sent by the SIM the reader
must timeout and send an error message back to the host.

Change-Id: Iacd6aacaf8220e69b9b7038e354d54c788d1eb05
Andreas Eversberg at

#28747 (Jun 18, 2026, 12:17:07 PM)

CCID: Add testenv.cfg to run tests using testenv

Change-Id: I97c9da414facf438aa28d5200c4152730ff763a2
Andreas Eversberg at

#28746 (Jun 18, 2026, 12:17:03 PM)

CCID: Send a wrong procedure byte towards the reader

A case 3 request is send and a response with data is expected, but the
first byte replied by the sim is not a procedure byte, nor a valid
status byte.

This text expects the reader to return an error that states an incorrect
received procedure byte.

Change-Id: Iaa0bd8845b3408fba309874fe41c855d8e7efccc
Andreas Eversberg at

#28745 (Jun 18, 2026, 12:16:59 PM)

CCID: Send procedure byte, when not expected

A case 1 APDU does not request any data from SIM to return. The SIM will
only return a status byte with no procedure byte in advance.

The test sends a procedure byte in advance of the two status bytes
towards the reader. The reader expects SW1 instead of the status byte,
so that it returns it as SW1.

Change-Id: Icffd48d99f0eb48e0898efb027854eba8c22f4a4
Andreas Eversberg at

#28744 (Jun 18, 2026, 12:16:41 PM)

CCID: Check if reader accepts highest P3 value 0xff

This test should ensure that there is no buffer overflow when receiving
large responses from SIM.

Change-Id: I298795d791f2964758bd4792e10131f92cf561bc
Andreas Eversberg at

#28743 (Jun 18, 2026, 12:16:33 PM)

CCID: Check if reader handles special P3 value 0x00 correctly

If data is requested from SIM with P3 set 0x00, it means that 256
bytes are requested. The reader will receive a procedure byte, which
must cause it to receive all 256 data bytes + two status words.

Change-Id: Icc3fd1937b9829fcf825c58d7b676aa2be2c48e7
Andreas Eversberg at

#28742 (Jun 18, 2026, 12:15:20 PM)

CCID: Check response of reader with empty SIM carrier

The reader has a SIM carrier inserted, but there is no response from the
SIM while expecting the ATR. The reader will get a timeout and is
expected to respond with a suitable error code.

The test uses the slot with the SIMtrace inserted. The SIMtrace will not
respond with an ATR. This way there is no (extra) empty slot required
for this test.

Change-Id: Ifebdcce8f9dd9a51de5a5cb6cf223041d5c38622
Andreas Eversberg at

#28741 (Jun 18, 2026, 12:15:14 PM)

CCID: Check if reader restarts WWT upon NULL procedure byte

The reader will receive a NULL procedure byte every 0.2 for a long time.
The reader may only respond with a status that time extension was
requested. At the end the SIM proceeds with a valid response. This
response must be returned by the reader.

Change-Id: I4eb09e86f88df19d96e9ec55872654352ca2ebd5
Andreas Eversberg at

#28740 (Jun 18, 2026, 12:11:09 PM)

CCID: Send procedure byte, when not expected

A case 1 APDU does not request any data from SIM to return. The SIM will
only return a status byte with no procedure byte in advance.

The test sends a procedure byte in advance of the two status bytes
towards the reader. The reader expects SW1 instead of the status byte,
so that it returns it as SW1.

Change-Id: Icffd48d99f0eb48e0898efb027854eba8c22f4a4
Andreas Eversberg at

#28739 (Jun 18, 2026, 12:11:05 PM)

CCID: Add testenv.cfg to run tests using testenv

Change-Id: I97c9da414facf438aa28d5200c4152730ff763a2
Andreas Eversberg at

#28738 (Jun 18, 2026, 12:11:00 PM)

CCID: Check if reader sends request TPDU with maximum size

The maximum size of a request TPDU can have 5 bytes header and 255 bytes
data. It is expected that the reader transmits all bytes to SIM without
failure.

Change-Id: I7c1cb52b578c19d6c0ec1493e45f6ed9c43735b4
Andreas Eversberg at

#28737 (Jun 18, 2026, 12:10:55 PM)

CCID: Send a wrong procedure byte towards the reader

A case 3 request is send and a response with data is expected, but the
first byte replied by the sim is not a procedure byte, nor a valid
status byte.

This text expects the reader to return an error that states an incorrect
received procedure byte.

Change-Id: Iaa0bd8845b3408fba309874fe41c855d8e7efccc
Andreas Eversberg at

#28736 (Jun 18, 2026, 12:10:51 PM)

CCID: Check if reader accepts highest P3 value 0xff

This test should ensure that there is no buffer overflow when receiving
large responses from SIM.

Change-Id: I298795d791f2964758bd4792e10131f92cf561bc
Andreas Eversberg at

#28735 (Jun 18, 2026, 12:10:43 PM)

CCID: Check if reader handles Abort correctly

This test fails with osmo-ccid-firmware, because it is not yet
implemented.

Change-Id: Iebe97e73497b8468ebf08faf2c4db700fc76997f
Andreas Eversberg at

#28734 (Jun 18, 2026, 12:10:35 PM)

CCID: Check if reader restarts WWT upon NULL procedure byte

The reader will receive a NULL procedure byte every 0.2 for a long time.
The reader may only respond with a status that time extension was
requested. At the end the SIM proceeds with a valid response. This
response must be returned by the reader.

Change-Id: I4eb09e86f88df19d96e9ec55872654352ca2ebd5
Andreas Eversberg at

#28733 (Jun 18, 2026, 12:10:29 PM)

CCID: Check if reader handles special P3 value 0x00 correctly

If data is requested from SIM with P3 set 0x00, it means that 256
bytes are requested. The reader will receive a procedure byte, which
must cause it to receive all 256 data bytes + two status words.

Change-Id: Icc3fd1937b9829fcf825c58d7b676aa2be2c48e7
Andreas Eversberg at

#28732 (Jun 18, 2026, 12:10:16 PM)

CCID: Check if reader times out while expecting status words

A case 1 APDU is sent toward the reader. The reader expects two status
words. If none of these are sent by the SIM the reader must timeout and
send an error message back to the host.

Change-Id: I054b56a9e2f10e5b984ad0398efb4be5696ce16c
Andreas Eversberg at

#28731 (Jun 18, 2026, 12:10:07 PM)

SIMTRACE: Increase USB receive buffer size

The maximum SIM request data can be 255 bytes. Additionally, the
SIMtrace PDU header is 14 bytes. So increase the buffer to 269 bytes.

Change-Id: I05261b4a754b4892955d0b4e426bd32be261efa7
Andreas Eversberg at

#28730 (Jun 18, 2026, 12:08:16 PM)

CCID: Check if reader times out while expecting procedure byte

A case 3 APDU is sent toward the reader. The reader expects a procedure
byte or a status word. If none of these are sent by the SIM the reader
must timeout and send an error message back to the host.

Change-Id: Iacd6aacaf8220e69b9b7038e354d54c788d1eb05
Andreas Eversberg at

#28729 (Jun 18, 2026, 12:08:09 PM)

CCID: Check response of reader with empty SIM carrier

The reader has a SIM carrier inserted, but there is no response from the
SIM while expecting the ATR. The reader will get a timeout and is
expected to respond with a suitable error code.

The test uses the slot with the SIMtrace inserted. The SIMtrace will not
respond with an ATR. This way there is no (extra) empty slot required
for this test.

Change-Id: Ifebdcce8f9dd9a51de5a5cb6cf223041d5c38622
Andreas Eversberg at

#28728 (Jun 17, 2026, 11:50:19 PM)

osmo-bts-trx: shut down on stale clock indication from transceiver

We expect the transceiver to be a reliable, monotonic clock source.
If it reports an FN far behind our local timer (elapsed_fn < 0) while
far more wall-clock time elapsed than its FN advance accounts for,
its clock has likely stalled and the indication carries a stale frame
number.  Acting on it drags the scheduler backwards and re-transmits
already-sent TDMA frames, corrupting lchan-internal state(s).

Detect this and shut down the process, same rationale as the existing
"PC clock skew too high" check in trx_fn_timer_cb().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: If787ab7ed70aa2dcb0389ceb58620c2302c3431a
Related: OS#7020, OS#6794
Vadim Yanitskiy at

#28727 (Jun 17, 2026, 10:28:26 PM)

osmo-bts-trx: reset BTS GSM time on clock (re)start

trx_sched_clock_started() is called when the transceiver is powered
on, e.g. after an A-bis link re-establishment, which in ttcn3-bts-test
happens once per testcase.  The transceiver restarts its TDMA frame
number from ~0, but we only reset the per-TRX clock state (tcs),
leaving bts->gsm_time.fn at the previous epoch's value.

As a result the first (low) FN reported by the transceiver is mistaken
for a huge backwards jump, e.g.:

  l1sap.c:628 Invalid condition detected: Frame difference is 102-10386=2705364 > 1!

Reset bts->gsm_time to FN 0 here so each clock epoch starts clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: Id8da126e460d3846a3be5bdb271553457fdd0590
Vadim Yanitskiy at

#28726 (Jun 17, 2026, 1:56:04 PM)

server: do not abort process on short conn message

conn_read_cb() used OSMO_ASSERT() to check that the received
message holds at least a full osmo_pcap_data header.  Although
conn_segmentation_cb2() should only ever hand up complete frames,
asserting on a length derived from network input means a framing
anomaly would abort the entire server (taking down all other clients'
captures).  Close the offending connection gracefully instead,
consistent with the other error paths in this function.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: Ia102ff918ef8152d212e10a860f5dc70efec880b
Vadim Yanitskiy at

#28725 (Jun 17, 2026, 1:56:01 PM)

tls: do not treat GNUTLS_E_AGAIN/INTERRUPTED as fatal on read

osmo_tls_client_bfd_cb() treated any non-positive return from
gnutls_record_recv() as a fatal error and tore down the session.  On a
non-blocking socket gnutls_record_recv() can return GNUTLS_E_AGAIN or
GNUTLS_E_INTERRUPTED (both negative but non-fatal), which would drop
an otherwise healthy TLS session.  Handle them as retryable, mirroring
the existing logic in tls_write().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: If2f842b202dd08c07dffe3770c51cf0ce886beee
Vadim Yanitskiy at

#28724 (Jun 17, 2026, 1:55:58 PM)

tls: fix broken certificate hostname verification

verify_cert_cb() retrieved the gnutls session pointer and passed it to
gnutls_certificate_verify_peers3() as the expected hostname.  But the
session pointer is set to the osmo_tls_session struct (it is needed by
cert_callback()), not a hostname string.  Hostname matching was
therefore performed against raw struct bytes, rendering verification
meaningless and potentially reading out of bounds, even when
"tls verify-cert" was enabled.

Store the configured hostname in struct osmo_tls_session and have
verify_cert_cb() read it from there.  Also drop the stray
gnutls_certificate_verify_peers3() call in the client setup: it ran
before any handshake (so there were no peer certificates yet) and its
result was ignored; the real verification happens via the registered
callback during the handshake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: If64950a698bfcfbf556a37ef1be3e68abc124384
Vadim Yanitskiy at

#28723 (Jun 17, 2026, 1:55:53 PM)

server: fix zmq message leak on send failure

zmq_msg_send() only transfers ownership of the message to ZeroMQ on
success.  On failure the caller retains ownership, so the previously
init'd zmq_msg_t was leaked on every failed publish.  Close it
explicitly on the error path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I501b1bf55bede4e69fa5d9b3f38d87341482ff49
Vadim Yanitskiy at

#28722 (Jun 17, 2026, 1:55:50 PM)

client: Fix 32-bit overflow when computing pcapng EPB timestamp

tv_sec * 1000 * 1000 was evaluated in int arithmetic.  Where time_t /
tv_sec is 32-bit, this overflows for any tv_sec > ~2147, corrupting
the 64-bit timestamp_usec well before the year 2038.  Cast tv_sec to
uint64_t before the multiplication so the whole expression
is computed in 64 bits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I20d3282b8cba1675ce2d0860e66027e5ee8245ef
Vadim Yanitskiy at

#28721 (Jun 17, 2026, 1:55:48 PM)

client: fix off-by-one in wrapped pcap stats counter

When a libpcap stats counter (ps_recv/ps_drop/ps_ifdrop) wraps around
UINT_MAX, get_psbl_wrapped_ctr() computed the delta as
(UINT_MAX - old_val) + new_val, omitting the single increment that
takes the counter from UINT_MAX through zero.  Add the missing +1 so
the reported delta matches the real number of increments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I66581910dbd1e955831a6ff913042059ad4994a7
Vadim Yanitskiy at

#28720 (Jun 17, 2026, 1:55:45 PM)

server: fix NULL deref of file_hdr_msg when store is disabled

When a connection has storing disabled (no store), conn->file_hdr_msg
is never populated.  The previous link-header handling skipped the
first branch (gated on conn->store) and fell through to the comparison
branch, which dereferenced the still-NULL conn->file_hdr_msg, crashing
the server on the first PKT_LINK_HDR from such a client.

Gate the whole header tracking on conn->store and simply free the
message when not storing, since osmo_pcap_conn_restart_trace() already
no-ops in that case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I419e1b66d07307c3e49294984887c153cd8494c3
Vadim Yanitskiy at

#28719 (Jun 17, 2026, 1:55:42 PM)

client: vty: do not print NULL tls hostname

conn->tls_hostname defaults to NULL and can be cleared via "no tls
hostname".  Writing it unconditionally emitted a "tls hostname (null)"
line, producing a config that does not re-parse.  Guard it like the
other optional tls fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I5b920337409d8c9fa1edb8d47177882cf0a6c4e7
Vadim Yanitskiy at

#28718 (Jun 17, 2026, 1:55:38 PM)

client: honor IPv4 header length in GPRS filter

The GPRS-NS/BSSGP filter assumed a fixed 20-byte IPv4 header (IP_LEN)
when locating the UDP header and payload.  When the captured packet
carries IPv4 options (ip_hl > 5), udp_data/payload_data pointed into
the middle of the headers and check_gprs() parsed garbage, classifying
packets incorrectly.

Use the actual header length from ip_hl, reject malformed headers
(ip_hl < 5), and re-validate that the larger headers fit within the
captured length before computing the payload.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: Iac1fa9cc2a3c06cbe19c3e7799a0b335f2e3dda9
Vadim Yanitskiy at

#28717 (Jun 17, 2026, 1:55:34 PM)

server: vty: validate rotate-localtime modulus against the new interval

apply_rotate_localtime() computed the maximum allowed modulus from
pcap_server->rotate_localtime.intv, the currently-stored (old) interval,
rather than the intv argument being applied.  On first configuration the
stored interval is the default 0, so the switch hit the default case and
rejected an otherwise valid command; when changing intervals the modulus
was bounds-checked against the wrong interval.  Switch on intv instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I0b367d4e255db3208b41e12adec682026b99cc18
Vadim Yanitskiy at

#28716 (Jun 17, 2026, 1:55:29 PM)

server: fix msgb leak on duplicate link header

rx_link_hdr() takes ownership of msg on success (rx_link() only frees
it on failure).  Both branches that call update_conn_file_hdr_msg()
free msg, but when an identical link header was already stored neither
branch ran and msg was leaked.

This happens on every duplicate PKT_LINK_HDR, e.g. a client that
periodically resends its header.  Free msg explicitly in that case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: I79344fe942342f2a736878142b3cf036fc982eef
Vadim Yanitskiy at

#28715 (Jun 17, 2026, 1:54:17 PM)

server: fix misleading data length validation log message

The format string "%u < %u <= %u" was printed with arguments
(min_len, data->len, max_len), placing the offending length in
the middle and mislabeling it.  This is confusing.  Let's print
the actual length followed by the expected interval instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: Ice95c1f8ad1aa8de259364bd70eba0db8918b19e
Vadim Yanitskiy at

#28714 (Jun 17, 2026, 1:50:26 PM)

server: vty: fix docs for cfg_server_rotate_localtime[_mod_n]

Change-Id: I6fd1d081bba035fbd9d72a1705ab58194edf274e
Fixes: 18747641 ("pcap-server: Make rotate-localtime feature configurable through VTY")
Vadim Yanitskiy at

#28713 (Jun 17, 2026, 12:57:24 PM)

vty: clamp configured snaplen to the wire-framing limit

osmo-pcap carries each captured packet in a frame whose length field
(struct osmo_pcap_data.len) is a uint16_t, so any snaplen above ~64 KiB
cannot be transported and is silently clamped by the server when sizing
its receive buffer (calc_data_max_len() caps at UINT16_MAX). The VTY,
however, advertised libpcap's MAXIMUM_SNAPLEN (262144), misleading users
into configuring values that never take effect.

Introduce OSMO_PCAP_MAX_SNAPLEN (65535) and, in both the client "pcap
snaplen" and server "max-snaplen" handlers, warn and cap the value to it
when a larger one is given. The command syntax keeps the <1-262144>
range for backwards compatibility so existing configs still parse; the
help text now documents the effective 64 KiB limit.

Related: SYS#8099
Related: 6d2f7c52 ("server: Limit rx buffer size to UINT16_MAX")
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Change-Id: Ia56cad48e8cefe8ae103f2f7d2e037bf28438b71
Vadim Yanitskiy at

#28712 (Jun 17, 2026, 12:57:22 PM)

doc: clarify 'pcap snaplen' / 'max-snaplen'

Change-Id: Ic2c82173c12814d61f0ee9f7454b9e5dcb0c13f4
Related: SYS#8099
Vadim Yanitskiy at