ogs_pco_parse() previously relied on ogs_assert() to verify the bounds
of Protocol/Container fields while parsing PCO/EPCO data. If the outer
PCO/EPCO length was inconsistent with the internal container encoding
(e.g., truncated Container-ID, Container-Length, or container data),
the assert would trigger and terminate the process.
Because PCO/EPCO is derived from UE-supplied NAS messages (e.g.,
PDU Session Establishment Request), a malformed EPCO IE could trigger
a remote SMF crash, resulting in a denial-of-service condition.
This patch replaces the assert-based bounds checks with explicit
runtime validation and returns an error when malformed or truncated
PCO/EPCO is detected. The SMF can then reject the request cleanly
instead of aborting.
Checks added:
- Validate minimum PCO/EPCO length before accessing header fields
- Verify Container-ID bounds
- Verify Container-Length bounds
- Verify container payload length
- Detect container count overflow beyond
OGS_MAX_NUM_OF_PROTOCOL_OR_CONTAINER_ID
With these changes, malformed EPCO inputs are safely rejected and the
SMF remains operational.
Issues: #4341
Clear presence-driven fields before processing conditional IEs to prevent
stale state when find_or_add() returns an already-existing entry.
FAR: reset dst_if_type_presence and outer_header_creation_len
URR: reset all measurement/threshold/quota fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a PFCP control plane sends a Session Modification Request with
Create FAR, Create QER, or Create URR IEs for IDs that were not
previously created during PDR processing, the UPF rejects them with
"Cannot find [FAR|QER|URR]-ID[N] in PDR" errors.
This is because ogs_pfcp_handle_create_far/qer/urr() use
ogs_pfcp_[far|qer|urr]_find() which only looks up existing entries,
while ogs_pfcp_handle_create_pdr() correctly uses
ogs_pfcp_pdr_find_or_add() which creates new entries if needed.
In practice, some PFCP control planes (e.g., vendor-specific PGW-C
implementations) send Create URR/QER/FAR in Session Modification
without a corresponding Create PDR that would have pre-created these
entries. The resulting PFCP error responses cascade into GTP-U Error
Indications, causing bearer teardowns and IMS PDN disconnections.
This patch:
- Changes Create FAR/QER/URR handlers to use find_or_add, matching
the existing Create PDR behavior
- Makes Remove PDR/FAR/QER/URR handlers idempotent: removing a
non-existent entry now returns success with a warning instead of
failing with an error, since the desired state (entry removed) is
already achieved
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The AMF could abort when processing malformed or oversized multipart
SBI requests due to an assertion triggered in the multipart parser
callback.
When the parser encountered an overflow condition while assembling
multipart part data, `on_part_data()` executed `ogs_assert_if_reached()`,
causing the AMF process to terminate. This allowed malformed HTTP/2
multipart requests to trigger a denial-of-service condition.
This patch replaces the assertion-based failure with graceful error
handling:
- Introduce `multipart_part_data_t` and explicit parser state tracking.
- Add `parse_error` flag to propagate parsing failures.
- Validate the result of `multipart_parser_execute()`.
- Reject malformed multipart payloads instead of aborting.
- Replace fatal assertions with error handling and proper cleanup.
- Add centralized cleanup via `multipart_parser_data_free()`.
As a result, malformed or oversized multipart bodies are now rejected
with an error, while the AMF process remains operational.
Issues: #4290
Two issues (#4277, #4278) reported crashes caused by malformed or
unexpected inputs.
In the TLV parser, several ogs_assert() checks could be triggered by
malformed TLV blocks, resulting in process termination. These checks
are replaced with proper error handling: the parser now logs the error,
limits hexdump size, frees allocated TLVs, and returns NULL instead of
aborting.
In the SMF S5-C Create Session Request handler, additional validation
is introduced for Bearer Context handling. The implementation now
rejects requests containing multiple Bearer Contexts, missing mandatory
fields (EBI or Bearer QoS), duplicate EBI values, or invalid TEID/IP
information. Several ogs_assert() calls that could be triggered by
malformed messages are also replaced with explicit error handling.
These changes prevent crashes caused by malformed TLV blocks or
unexpected Bearer Context structures and ensure the SMF rejects such
requests gracefully.
Issues: #4277, #4278
Several users reported intermittent AMF crashes when SM Context Update
procedures overlap with NG context release or a new Registration
procedure. In these situations the RAN-UE associated with a session may
change before the asynchronous SBI response arrives.
Typical trigger scenarios include:
* UEContextReleaseRequest followed by a new Registration Request
* PDU Session Update overlapping with UE deactivation or handover
* Registration Request arriving while a previous Service Request is
still being processed
In these cases the AMF may send an Update SM Context request to the SMF
while the NG context is being released or replaced. When the asynchronous
SBI response arrives later, the AMF uses the session's current ran_ue
pointer. However, that pointer may already have been switched to a new
RAN-UE or cleared due to the release procedure.
As a result, the AMF may reference the wrong RAN-UE context or an
inconsistent state, eventually triggering an assertion such as:
amf_nsmf_pdusession_handle_update_sm_context:
Assertion `ran_ue->deactivation.group' failed
The root cause is that SBI client transactions do not preserve the
RAN-UE association at the time the request was sent. Because SBI
operations are asynchronous, the session context may change before the
response is processed.
This patch introduces a generic mechanism to attach user-defined context
to an SBI transaction:
- Add `user_data` and `user_data_free` to `ogs_sbi_xact_t`
- Allow NF-specific code to store per-transaction context
- Ensure the memory is released automatically when the transaction
is removed
The AMF now stores a snapshot of the RAN-UE ID in the SBI transaction
when sending an Update SM Context request. When the SBI response is
processed, the AMF retrieves the RAN-UE using this snapshot instead of
the session's current ran_ue pointer. This guarantees that the response
is associated with the correct RAN context even if the session state has
changed in the meantime.
This approach avoids race conditions between asynchronous SBI responses
and NG context lifecycle events, preventing the AMF from accessing an
incorrect or partially released RAN-UE context.
Reported-by:
multiple users on v2.7.6 environments
Issues: #4174, #4274
Replace ogs_assert() checks in ogs_gtp2_parse_tft() with explicit
runtime length validation to prevent process abort on malformed
TFT/TAD IEs.
Previously, insufficient length checks could trigger assertion
failures when parsing crafted BearerResourceCommand messages with
invalid packet filter content lengths. This allowed a malformed
TFT/TAD IE to cause a crash (SIGABRT) in SMF.
This patch:
- Adds explicit boundary checks before every field access
- Validates that content.length does not exceed remaining IE length
- Protects component array bounds during parsing
- Logs errors and returns current parsed size instead of aborting
The function now gracefully rejects malformed input without
terminating the process, preventing potential denial-of-service
conditions on S5-C interface.
No functional change for valid messages.
Issues: #4281
Replace strtoll() with strtoull() in ogs_uint64_from_string() and
remove fatal abort on conversion errors to prevent remote crash via
malformed SupportedFeatures/requester-features values.
The previous implementation could trigger OGS_LOG_FATAL and
ogs_assert_if_reached() when strtoll() detected ERANGE, allowing a
malicious or buggy peer to cause a denial-of-service by sending an
overly large hexadecimal value.
Changes:
- Use strtoull() for proper unsigned parsing.
- Add strict endptr validation (no digits, trailing garbage).
- Handle ERANGE and invalid inputs gracefully without abort().
- Normalize errno handling: success paths set errno=0.
- In ogs_sbi_parse_request(), reject invalid requester-features
(EINVAL/ERANGE) and return OGS_ERROR instead of proceeding.
Empty string is treated as valid (0), consistent with 3GPP
SupportedFeatures pattern ('^[A-Fa-f0-9]*$').
This ensures malformed requester-features values no longer crash
NRF and are properly rejected during SBI request parsing.
Issues: #4263
open5gs doesn't support the "SMS in MME" (3GPP TS 23.272 Annex C) yet,
so better announce that we support SGs interface than giving no
information the the HSS.
Replace hard assertions with boundary checks when parsing
SMF and AMF information from NRF NFProfile.
Previously, multiple ogs_assert() conditions assumed that
slice, TAI, TAI range, and GUAMI counts would always remain
within static limits (e.g., OGS_MAX_NUM_OF_SLICE,
OGS_MAX_NUM_OF_TAI, OGS_MAX_NUM_OF_SERVED_GUAMI).
If NRF provided NFProfile data exceeding these limits,
the process could terminate due to assertion failure,
resulting in service instability.
This patch introduces explicit overflow validation:
- SMF
- Slice list overflow protection
- NR TAI list overflow protection
- NR TAI range TAC index overflow protection
- AMF
- Served GUAMI overflow protection
- NR TAI range overflow protection
When limits are exceeded, an error log is generated and
parsing of the affected list is stopped gracefully,
preventing crash while preserving existing data.
This improves robustness against malformed or excessive
NFProfile inputs from NRF or peer NFs.
Issues: #4249, #4250, #4252
Fix a crash triggered by SCP NFProfile registrations that do not
provide any usable endpoint information.
Previously, ogs_sbi_client_associate() asserted that a client must
exist after association. However, malformed or incomplete NFProfiles
(e.g., scpInfo containing only scpDomainInfoList without scpPorts or
instance/service endpoints) could bypass endpoint validation and
result in no client being created.
This led to an assertion failure in:
ogs_sbi_client_associate()
-> ogs_assert(client)
Root causes addressed:
1. Association safety
- Remove hard assertion on missing instance-level client.
- Perform association only when a client exists.
- Improve logging for missing instance/service endpoints.
2. Endpoint validation refactor
- Move endpoint validation after client association.
- Introduce nf_instance_has_usable_client() helper to verify:
* Instance-level client, or
* Any service-level client.
3. Registration rejection
- Reject NFProfile registrations that lack usable endpoints
with HTTP 400 instead of allowing inconsistent state.
4. SCP info handling
- Treat domain-only SCP registrations as valid nf_info inputs
when num_of_domain is present.
Impact:
- Prevents assertion crashes in NRF triggered by malformed SCP
registrations.
- Ensures NF instances are accepted only when at least one usable
endpoint is available.
- Improves diagnostic logging for operator troubleshooting.
Tested with:
- SCP registration containing only scpDomainInfoList
- Registrations with instance-level endpoints
- Registrations with service-level endpoints
Issues: #4243, #4248
Enforce a 256MB maximum payload size in
on_data_chunk_recv() to prevent excessive memory allocation
from large HTTP/2 DATA frames.
Requests exceeding the limit are rejected with HTTP 413,
and allocation failures return HTTP 503.
This mitigates large payload DoS conditions.
Issues: #4244, #4247
When an NF loses heartbeat and enters re-registration, existing
NRF subscription states tied to the previous NF instance remain
both remotely (NRF) and locally (subscription_data pool).
In environments with repeated heartbeat loss or timing races
(e.g., docker-compose deployments), this leads to continuous
re-subscription loops and unbounded growth of
subscription_data entries, eventually exhausting the pool and
triggering assertion failures in ogs_sbi_subscription_data_add().
This patch introduces a pre-registration cleanup mechanism:
- Send DELETE requests for all subscriptions associated with
the NF instance before re-registration.
- Perform asynchronous local cleanup in the unsubscribe
response handler (avoiding use-after-free and double free).
- Add duplicate DELETE guard using subscription flags.
- Improve logging visibility for subscription cleanup flow.
This ensures that stale NRF subscription states are removed
and prevents subscription_data pool exhaustion during
re-registration loops.
Issues: #4207
NFProfile plmn_list returned from NRF overwrites the local serving
PLMN configuration. Reset num_of_serving_plmn_id instead of the
unused nf_instance->num_of_plmn_id to avoid stale accumulation.
Issues: #4207
Bug:
A double-free scenario in the error handling path:
When ogs_sbi_send_request_with_sepp_discovery failed, it called
ogs_sbi_xact_remove(xact) internally.
The function then returned false to its caller. The caller
(smf_sbi_discover_and_send) also called ogs_sbi_xact_remove(xact)
on failure.
This caused the discovery_option structure to be freed twice,
leading to the valgrind error:
```
==90== Invalid read of size 8
==90== at 0x49AFBB6: ogs_sbi_discovery_option_free (message.c:3633)
==90== by 0x49CC100: ogs_sbi_xact_remove (context.c:2674)
==90== by 0x407DDDC: smf_sbi_discover_and_send (sbi-path.c:392)
```
Fix:
Now the function follows proper resource ownership semantics:
the caller who creates the transaction is responsible for cleanup
when the function fails, making the error handling consistent and
preventing double-free issues.
Added missing cleanup to ogs_sbi_send_request_to_nf_instance and
af_sbi_discover_and_send.
Avoid aborting on malformed or oversized GTP messages that exhaust the
internal TLV pool.
- Replace ogs_assert() in ogs_tlv_get() with error handling and NULL return
- Detect TLV allocation and parsing failures in ogs_tlv_parse_block()
- Clean up partially parsed TLVs and return failure instead of aborting
- Limit hexdump size to prevent log flooding on malformed input
This prevents a single malformed message from crashing SGW-C/PGW-C/MME
and ensures graceful failure when TLV allocation or parsing fails.
Issues: #4234
Replace ogs_assert() and ogs_fatal() with runtime checks when allocating
UE contexts, transactions, and timers.
Handle pool and timer exhaustion gracefully by logging errors, cleaning
up partially created objects, and returning NULL instead of aborting
the process, improving control-plane robustness under high load or
resource limits.
Issues: #4220, #4221
Remove hard assertions in GTPv2 Bearer QoS and Flow QoS parsers and
replace them with defensive length validation. Invalid IEs are now
gracefully rejected by the caller instead of aborting the process.
Update SGW-C and SMF handlers to validate parser results and return
appropriate GTP-C error causes, preventing daemon crashes on malformed
GTPv2 messages.
Issues: #4217
Align full-DNN construction with 3GPP TS 23.003 §9.1.2 by switching the
Operator Identifier format from "5gc.mncXXX.mccYYY.3gppnetwork.org" to
"mncXXX.mccYYY.gprs". Introduce new helper utilities to extract and build
OI (Operator Identifier) from both PLMN-ID and FQDN, and replace the
legacy `ogs_home_network_domain_from_fqdn()` usage in AMF/SMF/PCF paths.
This resolves DNN misalignment in vSMF–hSMF PDU Session Create that
caused interop issues with external 5G core vendors during HR roaming.
Includes updates across AMF/SMF/PCF, unit tests, and supporting helpers.
Issues: #4096
When CreatePDR/PDI contains an F-TEID IE with length 0, SGWU aborted due to
assertion `pdr->f_teid.ipv4 || pdr->f_teid.ipv6` in ogs_pfcp_handle_create_pdr().
This allowed a malformed PFCP Session Establishment Request to remotely crash SGWU.
This patch adds validation for:
- Zero-length F-TEID IE (return INVALID_LENGTH)
- F-TEID without IPv4/IPv6 flag (return INVALID_F_TEID_ALLOCATION_OPTION)
Instead of asserting and aborting, SGWU now rejects the request gracefully by
returning an appropriate Cause/Offending IE.
Issues: #4182
This patch replaces fatal ogs_assert() calls in PFCP object allocation
(ogs_pfcp_{pdr,far,urr,qer}_find_or_add) with graceful error handling.
Previously, exceeding per-session resource limits (e.g., QER pool overflow
triggered via CreatePDR referencing undeclared QER-ID) would cause a process
abort in open5gs-upfd, leading to a remote denial-of-service condition.
The handler now returns PFCP Cause=NO_RESOURCES_AVAILABLE and properly
rejects malformed or resource-exhausting PFCP Session Establishment requests,
allowing the UPF to continue running without terminating all existing sessions.
Fixes: DoS vulnerability triggered by excessive implicit QER allocation.
Issues: #4181
Replace `ogs_assert(nxt == 0)` with validation and graceful error return
when parsing IPv6 jumbo payload where plen=0 but NextHeader is non-zero.
This prevents open5gs-upfd from aborting when receiving a single malformed
GTP-U IPv6 packet crafted to trigger assertion failure, resulting in a
remote DoS condition.
Malformed packets are now safely dropped and logged instead of terminating
the UPF process.
Issues: #4180
According to TS 29.244, FAR-ID is a mandatory IE in CreatePDR. However,
Open5GS previously accepted a Session Establishment Request containing a
CreatePDR without FAR-ID. When subsequent GTP-U packets matched the PDR,
the user-plane fast path dereferenced a NULL FAR pointer and aborted,
leading to a UPF crash (DoS).
This patch adds mandatory IE validation for FAR-ID in
ogs_pfcp_handle_create_pdr(), returning PFCP cause
MANDATORY_IE_MISSING when FAR-ID is absent.
As a result, malformed CreatePDR is rejected at PFCP control plane
instead of causing fatal assertion in the data path.
Fixes crash in `_gtpv1_u_recv_cb()` and improves robustness.
Issues: #4179
When receiving a PFCP Session Establishment Request containing a CreateURR
with an out-of-range URR-ID (e.g. 65535), UPF attempted to index
sess->urr_acc[] without bounds checking, leading to an assertion failure
and process abort.
This patch validates URR-ID before use and rejects the message gracefully
with an error cause if the value exceeds OGS_MAX_NUM_OF_URR. A clearer
log message is also added to indicate the valid range.
Fixes: assertion failure in upf_sess_urr_acc_timers_setup()
Issues: #4169
* AMF dynamic PLMNs via APIREST
* add new feature now we can register ues when plmn is deleted
* add documentation for use the API AMF-OAM
* update tutorial 08
* fix memory not freed
fix memory not freed
fix memory not freed
* improve releases ues of plmn
A malformed CER containing duplicate Auth-Application-Id AVPs caused
freeDiameter to trigger FD_LOG_FATAL within parserules_check_one_rule(),
reaching an unimplemented branch and calling abort(), which terminated
Open5GS daemons (HSS/MME/PCRF/AAA) using the freeDiameter stack.
To avoid crashing on invalid Diameter messages, remove the call to
ogs_assert_if_reached() inside FD_LOG_FATAL logging path. This allows
Open5GS to gracefully reject malformed messages instead of aborting.
Issues: #4155
UPF could crash when handling PFCP Session Establishment/Update
containing a CreateURR with a malformed Dropped-DL-Traffic-Threshold IE.
Added length validation for Dropped-DL-Traffic-Threshold and
Volume Measurement IEs to prevent buffer misuse and return an
appropriate PFCP cause and offending IE value.
Also removed assertion in IE parsing functions and replaced it with
error logging and validation checks.
Issues: #4154, #4152
When PFCP Session Establishment/Modification includes CreatePDR with F-TEID
(CH=1) whose address family flags (IPv4/IPv6) do not match the UPF's GTP-U
resource configuration for the target DNN (Network Instance), UPF asserted
and crashed in ogs_pfcp_object_teid_hash_set(). This occurred because the
existing logic assumed a matching address family and enforced it via
assert().
This patch replaces the assertions with proper validation and returns an
appropriate PFCP cause (REQUEST_REJECTED) when the address family does not
match, or if local F-TEID generation fails. This prevents UPF from crashing
and allows the SMF to receive a graceful failure response.
Changes:
- ogs_pfcp_object_teid_hash_set() now returns PFCP Cause instead of void
- Validate IPv4/IPv6 compatibility for DNN resource and local GTP-U address
- Replace assert() usage with runtime error handling and logging
- Integrate cause checking in SGWU/UPF N4 handlers for both Session
Establishment and Modification
- Avoids crash and reports REQUEST_REJECTED when mismatch occurs
Tested scenario:
- UPF with IPv4-only DNN resource receiving CH F-TEID with IPv6-only flags
(or vice versa) no longer causes crash.
Issues: #4315
This patch introduces assoc_id[] to ogs_sbi_xact_t and stores a snapshot
of the RAN-UE ID (AMF_ASSOC_RAN_UE_ID) when the AMF sends SBI requests
to SMF/PCF. Since the RAN-NG context may change (e.g., during NG
Context release or RRC re-establishment) before the asynchronous SBI
response arrives, relying on sess->ran_ue_id can lead to incorrect
context resolution. The transaction-level snapshot ensures that AMF
uses the correct RAN-UE when handling SBI responses.
Key changes:
- Added assoc_id[] array to ogs_sbi_xact_t.
- Stored RAN-UE snapshot for SBI Client operations.
- Updated AMF handlers (amf-sm, nsmf-handler, nnssf-handler,
nnrf-handler, sbi-path) to use xact->assoc_id[] instead of
sess->ran_ue_id for SBI Client responses.
- Updated NAMF handlers to continue using sess->ran_ue_id since they
operate in SBI Server mode and have no transaction snapshot.
- Refactored function signatures to pass amf_ue and ran_ue explicitly.
- Added detailed comments to sess->ran_ue_id explaining the distinction
between SBI Client and SBI Server behavior.
- Updated test cases and added the new issues4174 test.
This resolves the race where RAN-UE context changes between SBI request
and response, ensuring correct session processing and eliminating
RAN-UE lookup failures during asynchronous callbacks.
Issues #4174
Add explicit length checks for Maximum Bitrate and Guaranteed Bitrate
IEs in Create/Update QER handlers. When the IE length does not match
OGS_PFCP_BITRATE_LEN, return INVALID_LENGTH with the corresponding
offending IE type.
Also update ogs_pfcp_parse_bitrate() to log a detailed error message
and return 0 when the encoded IE length is invalid, instead of asserting.
This prevents crashes caused by malformed PFCP messages and ensures
correct cause/offending IE reporting to the peer.
Issues: #4152
- Added null-check for flow description direction token in ogs_ipfw_compile_rule()
to prevent dereferencing a NULL pointer.
- Replaced assertions with graceful error handling in Create/Update PDR handlers:
* Log failure when ogs_ipfw_compile_rule() returns error.
* Free allocated flow_description and remove the faulty PDR rule, then continue.
- Improved logging for invalid pdi.network_instance:
* Print length and include a hexdump of the invalid field.
Issues: #4151
Each time Prometheus scraper queried the metrics, there was a memory
leak. Depending on the amount of metrics, this could amount to some
5MB/h of memory leakage (in case of a scrape every 10 second).
Compiler outputs an error when compiling against libcurl 8.14.1-2ubuntu1
found in Ubuntu 25.10.
error: call to '_curl_easy_setopt_err_long' declared with attribute
warning: curl_easy_setopt expects a long argument [-Werror=attribute-warning]
Fix crash when discovery request specifies only DNN for SMF
The previous implementation could dereference a NULL s_nssai pointer
when handling discovery requests that contained only a DNN filter
(without any S-NSSAI). This caused an assertion failure inside
ogs_sbi_check_smf_info_slice(), which expects both arguments to be
non-null.
This patch fixes the issue by iterating over the SMF’s own slice list
and reusing each stored S-NSSAI when evaluating the DNN-only case.
The SMF instance now correctly matches any slice that provides the
requested DNN, avoiding a crash and restoring expected behavior.
The previous PR implemented the correct OR logic for multiple smfInfo
blocks but resulted in code that was harder to read. This commit rewrites
the logic in a simpler and clearer form without changing functionality.
The discovery matcher meant to accept an SMF instance when any advertised
smfInfo satisfied the requested S-NSSAI/DNN/TAI, but the previous logic
returned false as soon as one block missed the filters. That made configs
with multiple info blocks fail with “No SMF Instance”.
Track whether the request actually carries slice/TAI filters and mark the
instance as matched when at least one smfInfo passes them. Other NF types
keep their existing behaviour, while multi-block SMF configs now work as
documented.
Emergency numbers may be configured:
mme:
...
emergency:
dnn: internet.sos
number:
- digits: 110
categories: police
- digits: 112
categories: [ fire, ambulance ]
The categories are: police, ambulance, fire, marine, mountain
They are sent to the UE during attachment. Some UEs require this list
of numbers. When an emergency call is made, one of the given categories
is indicated towards the IMS in the INVITE message.
This patch consolidates the TAU handling logic for both
initialUEMessage and uplinkNASTransport cases, ensuring that the
EPS Bearer Context Status (BCS) check is always performed regardless
of active_flag or S1AP procedure type.
Key changes:
- Removed duplicated TAU handling code paths in emm-sm.c.
- Commonized KDF derivation and BCS validation under a single block.
- Introduced mme_ue->tracking_area_update_accept_proc to store
the selected S1AP procedure for TAU ACCEPT transmission.
- When e->s1ap_code == initialUEMessage and active_flag == 1,
TAU ACCEPT is sent via InitialContextSetup; otherwise via
DownlinkNASTransport.
- Applied the stored proc consistently across all handlers:
mme-path.c, mme-s11-handler.c, mme-s6a-handler.c, and sgsap-handler.c.
- Added fallback to DownlinkNASTransport if proc is not set.
- Cleared tracking_area_update_accept_proc after use to avoid reuse.
This ensures consistent TAU behavior for both initialUEMessage and
uplinkNASTransport flows, unified BCS mismatch handling