Any unexpected HTTP methods or resource names generate an error
and an assertion, ensuring that truly invalid cases are caught.
By adding these checks and early exits, we avoid fatal assertion failures
in scenarios where the AMF’s state machine would otherwise have no matching
transition for a late SBI callback.
In upf_sess_add, replace the unconditional assertion on sess with a check
that detects when the session pool is exhausted. If allocation fails,
log an error message (“Maximum number of Session reached”) and
return NULL instead of aborting the process.
This change prevents the UPF from crashing when the PFCP session limit (4096) is
exceeded and allows it to reject additional session establishment requests
cleanly.
In lib/sbi/message.c parse_multipart(), http->content may be NULL.
This occurs on empty-body multipart POSTs and causes a segfault.
Add guard to check http->content, log an error, and return OGS_ERROR.
In state_operational, guard against dispatching to NF instance FSMs whose
state has been reset to zero by ogs_fsm_fini() in event_termination(). Drop any
incoming SBI events for those instances and log an error, preventing assertion
failures when late HTTP callbacks arrive after an asynchronous SIGTERM shutdown.
In the previous implementation, the AMF would send a Partial-handover error
indication whenever it encountered a session not found in the subscriber DB,
even if valid sessions remained. This resulted in unexpected error responses
during NG handover.
To resolve this, we record the initial SMF transaction count before iterating
through the UE session list. Sessions without a valid SMF context now produce
a warning and are skipped, while continuing to send Handover Notify messages
for provisioned sessions. After processing, we compare the SMF transaction
count to the initial value. If no valid sessions were handled, we send a
Partial-handover error indication.
With this change, unprovisioned sessions no longer trigger a premature error
indication, allowing valid PDU sessions to complete NG handover successfully.
In lib/sbi/client.c, the conditional compilation for
CURLMOPT_MAX_CONCURRENT_STREAMS was using #ifdef, which does not
ensure the option is set when the symbol is undefined.
Replace the check with #if CURL_AT_LEAST_VERSION(7,67,0) so that the
client applies the max concurrent streams setting on supported
libcurl versions. This fixes pool.event always showing the default
value and enables dynamic adjustment according to pool.stream.
SMF constructs up2cp FAR's outer_header_creation with |ogs_gtp_self()->gtpu_ip|
as DST IP address. Therefore, set |ogs_gtp_self()->gtpu_ip| to GTPU advertise
address. If advertise addr is not set, fall back to socket address as usual.
According to 3GPP TS 29.272 Annex A, when the HSS/UDM responds with
DIAMETER_ERROR_USER_UNKNOWN (5001), the MME/AMF should respond to the UE with
NAS EMM cause #8 (EPS services and non-EPS services not allowed), rather than
cause #11 (PLMN not allowed).
Previously, Open5GS returned cause #11 by default. However, this behavior is
problematic for private LTE environments where multiple operators may use the
same PLMN (e.g., 999/99 as per ITU-T E.212). In such cases, a UE rejected
with cause #11 will add the PLMN to its Forbidden PLMN list (FPLMN), causing
the device to avoid that PLMN for an extended period—even if another
compatible private network using the same PLMN exists.
This patch restores compliance with TS 29.272 by changing the default mapping
from cause #11 to cause #8 in both the 4G MME (emm_cause_from_diameter) and
5G AMF (gmm_cause_from_sbi) when handling unknown subscriber cases.
This ensures:
- Standard-conformant behavior across networks
- Better UE behavior in roaming or private LTE scenarios
- Avoids unnecessary FPLMN blacklisting in UE
Reference Issues:
- #263
- #1281
- #1332
Prevent crashes when UE context is missing in AMF and MME by replacing direct
assertions with conditional checks and error logging.
Removed unconditional ogs_assert(ran_ue) in AMF's GMM handlers and
ogs_assert(enb_ue) in MME's EMM handlers.
Now, if the UE context lookup returns NULL, log an error (including SUPI/IMSI,
NAS message type, and IDs), dump the NAS packet in hex for debugging,
and exit the handler gracefully instead of aborting.
Fix missing N2 signaling when tunnel information is unchanged,
causing AMF crash on repeated PathSwitchRequest
When a second PathSwitchRequest arrives without any tunnel changes,
the handler previously returned HTTP 204 No Content and omitted N2 information.
This led to a fatal assertion in the AMF SM context, since it expected
to receive updated N2 data even when the tunnel remained the same.
This patch modifies ngap_handle_path_switch_request_transfer to build
and send the N2 SM buffer in the “else” branch.
It calls ngap_build_path_switch_request_ack_transfer to construct
the Path Switch Request Acknowledge N2 message and then delivers it
with smf_sbi_send_sm_context_updated_data_n2smbuf.
A new test case is also added to verify that N2 signaling is correctly
transmitted when tunnel parameters have not changed.
In src/smf/context.c:
- Wrap UPF selection logic in a conditional that checks if pfcp_node
is non-NULL.
- If no UPF is available (pfcp_node == NULL), log an error and assert
that sess->pfcp_node remains NULL, instead of crashing.
- Only call selected_upf_node() and set up the GTP session when a prior UPF
entry exists.
In src/smf/gn-handler.c:
- After invoking smf_sess_select_upf(), verify sess->pfcp_node.
- If no UPF was selected, log an error ("No UPF available for session") and
return OGS_GTP1_CAUSE_SYSTEM_FAILURE instead of asserting.
In src/smf/s5c-handler.c:
- Mirror the same check for sess->pfcp_node after smf_sess_select_upf().
- If no UPF is available, log an error and return
OGS_GTP2_CAUSE_SYSTEM_FAILURE.
- If the selected UPF is not yet PFCP-associated, log a specific error
message and return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING.
These changes ensure that SMF does not abort when no UPF is configured or
associated; instead, it fails the session request with an appropriate GTP cause.
* [AMF] Fix UE context transfer when only NRF is client
If UE context transfer is initiated and the new AMF does not get the
old AMF from NRF or no UE context is retrieved from the old AMF,
we do not want to reject UE registration. Send identity request instead.
Test "transfer-error-case" is added into the commit.
* [tests] Unite tests for UE context transfer
All tests for UE context transfer with different configs are placed
into test folder transfer.
* [tests] Make two binaries for UE context transfer tests
For each test config a different test binary is created.
Previously, Open5GS assumed the _links map contained an array under the key
"items". However, the 3GPP specification (TS29.510 section 4.9.4 and TS29.501
Table 6.1.6.2.25-1) defines this member name as "item".
As a result, when interacting with vendor NRF implementations that use "item",
Open5GS could not find the array and logged "No items", causing JSON errors.
This change updates both serialization and parsing in lib/sbi/custom/links.c:
- In ogs_sbi_links_convertToJSON(), replace the property name "items" with
"item" when building JSON.
- In ogs_sbi_links_parseFromJSON(), retrieve the array under "item" and adjust
the error message to "No item" if the member is missing.
With these corrections, Open5GS will correctly handle NRF responses using "item"
and remain compliant with the indirect communication model defined by 3GPP.
In case AMF is configured for multiple PLMN's, it would send a wrong
GUAMI in the Registration Accept message to the UE, also in other NAS
and SBI messages. Previously, it would only send the first configured
PLMN.
In ipfw2.c errx() would call exit(), aborting the UPF thread on rule parse
errors. Add a macro mapping errx() to ogs_log_message() so errors are logged.
We no longer call exit() and the main loop continues on error.
Prior to this change, `session_write_callback()` unconditionally asserted that
`sbi_sess->poll.write` was non-NULL when the write queue drained, then removed
it from the poll set. In edge cases—particularly when using curl 8.x with
external epoll and `SIGPIPE` disabled—a late `EPOLLOUT` or errant write-ready
notification could arrive after `poll.write` had already been cleared. This
triggered the assertion in `nghttp2-server.c:1765`, aborting the process on
shutdown or session teardown.
This commit replaces the hard assertion with a runtime guard. If `poll.write`
is present, it is removed and reset to NULL as before. If it is already NULL,
we emit an warning log (`ogs_warn`) instead of aborting. This ensures any stray
write events after cleanup are safely ignored, allowing a clean exit without
crashing.
- Wrap `ogs_pollset_remove()` and pointer clear in `if (sbi_sess->poll.write)`
- Log an warning when `poll.write` is unexpectedly absent
- Preserve original behavior when `poll.write` is valid
This change resolves the fatal assertion observed on process exit after the
EPOLLERR/SIGPIPE fix and improves overall shutdown robustness.
Previously, any SCTP recv would trigger ogs_fatal and an assert_if_reached
when MSG_EOR wasn’t set, causing the AMF or MME to crash on oversized
or fragmented packets. Since we rely on a 32 KB receive buffer and
do not support SCTP reassembly, this change replaces the conditional
fatal/assert logic with a single ogs_error call in both ngap_recv_handler
and s1ap_recv_handler.
Oversized or partial SCTP messages are now logged and dropped instead of
crashing the process.
Previously, both AMF and MME assumed that RAN UE contexts would always
be present, triggering fatal assertions when a context lookup failed.
This change introduces explicit checks in the common_register_state handlers
to detect missing NG and S1 contexts without crashing:
- Check ran_ue existence and abort if NG context has already been removed
- Detect deassociated RAN-UE (invalid amf_ue_id) and
break to avoid further processing
- Validate AMF-UE ID matches ran_ue->amf_ue_id and skip on mismatch
- Replace hard assertions on MBR/GBR presence in S1AP e‐RAB setup
with a runtime check: if any of the four parameters (MBR DL/UL, GBR DL/UL)
is missing, log an error and treat the bearer as Non-GBR
- Mirror the same logic in SMF’s NGAP build routines for PDU Session Resource
Setup and Modify transfers: drop the assertions, emit detailed error messages
with the missing MBR/GBR values, and omit GBR IEs
- Ensures graceful handling of incomplete QoS configurations by defaulting
to best‐effort (Non-GBR) rather than crashing
Prevent the NRF from processing requests that target its own
instance ID. This prevents a denial of service vulnerability.
If an SBI request attempts to delete or modify the local NRF
instance, respond with 404 Not Found and log an error, avoiding
a crash due to the state machine assertion.
The token parsing loop in ogs_ipfw_compile_rule() lacked a bound on the
number of tokens stored in the 'av' array. This could overflow the stack
buffer when parsing overly long flow descriptions. Add a check to ensure
'i' remains below MAX_NUM_OF_TOKEN-2 before assigning to 'av[i]'.
- In `udm_ue_state_operational()`:
- Wrap the call to `udm_nudr_dr_handle_subscription_authentication()`
in an `if` check.
- On failure (`false`), log an error via
`ogs_error("udm_nudr_dr_handle_subscription_authentication() failed")`.
- Transition the FSM to `udm_ue_state_exception` using `OGS_FSM_TRAN()`.
This change ensures that failures during subscription authentication
REST calls are not silently ignored, and that the UE state machine moves into
an exception state for proper error handling and recovery.
In amf_context_parse_config(), update the loop condition to ensure that
((i * 2) + 1) remains below
(OGS_NAS_MAX_NETWORK_NAME_LEN - 1) before performing any writes.
This change prevents potential out-of-bounds memory writes during
the conversion of an ASCII string to USC-2, thereby fixing a buffer
overflow issue.
This issue was observed on Ubuntu 25.04 and reported in the osmocom
nightly package.
This commit adds support for two Supported-Features AVPs in the
UpdateLocationAnswer (ULA) to enable 5G-NSA roaming. The first AVP
includes subscriber restrictions, while the second AVP signals that NR
as Secondary RAT is supported. Updates include modifications to
lib/diameter/s6a/message.c, lib/diameter/s6a/message.h, and
src/hss/hss-s6a-path.c.
This commit enhances the SM Policy request sent to the PCF
by incorporating user location information and time zone data.
The SMF now builds a userLocationInfo structure using the session's NR TAI
and NR CGI details, along with a timestamp generated from the current GMT time.
Additionally, the UE's time zone is included in the request context,
and the ratType is explicitly set to NR.
In Open5GS 2.7.x, when using curl 8.x with external epoll, an issue occurred
where the peer connection was closed, triggering EPOLLERR. At this point,
POLL_OUT should have been set to trigger the write event handler, invoking
`event_cb()` and calling `curl_multi_socket_action`. This would allow
`curl_multi_info_read` to execute without blocking.
However, when `event_cb()` wasn't invoked, `curl_multi_socket_action` was
not called, causing `curl_multi_info_read` to block. This resulted in a busy
loop in epoll, continuously checking for the closed peer connection.
This issue specifically affects Open5GS 2.7.x with curl 8.x, and is observed
on Ubuntu versions starting from **noble** and later. It does not occur on
Ubuntu Jammy.
The solution involves globally ignoring SIGPIPE and fixing the epoll logic
to ensure POLL_OUT is triggered when EPOLLERR occurs, allowing `curl_multi_socket_action`
to be invoked and `curl_multi_info_read` to run non-blocking. This resolves
the busy loop and connection issues caused by peer disconnects when using
curl 8.x and external epoll.
This fix improves the stability and performance of Open5GS when used with
curl 8.x and Ubuntu versions **noble** and above.