diff --git a/configs/csfb.yaml.in b/configs/csfb.yaml.in index 9538a580e..53f19af8d 100644 --- a/configs/csfb.yaml.in +++ b/configs/csfb.yaml.in @@ -59,7 +59,7 @@ mme: smf: - address: 127.0.0.4 sgsap: - server: + client: - address: 127.0.0.2 map: tai: diff --git a/configs/open5gs/amf.yaml.in b/configs/open5gs/amf.yaml.in index 24e2c9757..3919c5c2c 100644 --- a/configs/open5gs/amf.yaml.in +++ b/configs/open5gs/amf.yaml.in @@ -59,43 +59,83 @@ amf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-amf.svc.local # sbi: # server: # - dev:eth0 # advertise: open5gs-amf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: amf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.5 and advertise as open5gs-amf.svc.local +# sbi: +# server: +# - address: 127.0.0.5 +# port: 7777 +# advertise: open5gs-amf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.5 +# port: 7777 +# advertise: open5gs-amf.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -117,6 +157,27 @@ amf: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/amf.key +# cert: @sysconfdir@/open5gs/tls/amf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/amf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/amf-client-sslkeylog.log +# sbi: +# server: +# - address: amf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/ausf.yaml.in b/configs/open5gs/ausf.yaml.in index db4c79f57..52291fdf7 100644 --- a/configs/open5gs/ausf.yaml.in +++ b/configs/open5gs/ausf.yaml.in @@ -22,43 +22,83 @@ ausf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-ausf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-ausf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: ausf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.11 and advertise as open5gs-ausf.svc.local +# sbi: +# server: +# - address: 127.0.0.11 +# port: 7777 +# advertise: open5gs-ausf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.11 +# port: 7777 +# advertise: open5gs-ausf.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -80,6 +120,27 @@ ausf: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/ausf.key +# cert: @sysconfdir@/open5gs/tls/ausf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/ausf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/ausf-client-sslkeylog.log +# sbi: +# server: +# - address: ausf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/bsf.yaml.in b/configs/open5gs/bsf.yaml.in index 37ceced21..12bc11433 100644 --- a/configs/open5gs/bsf.yaml.in +++ b/configs/open5gs/bsf.yaml.in @@ -22,43 +22,83 @@ bsf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-bsf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-bsf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: bsf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.15 and advertise as open5gs-bsf.svc.local +# sbi: +# server: +# - address: 127.0.0.15 +# port: 7777 +# advertise: open5gs-bsf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.15 +# port: 7777 +# advertise: open5gs-bsf.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -80,6 +120,27 @@ bsf: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/bsf.key +# cert: @sysconfdir@/open5gs/tls/bsf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/bsf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/bsf-client-sslkeylog.log +# sbi: +# server: +# - address: bsf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/mme.yaml.in b/configs/open5gs/mme.yaml.in index b3daf838d..39b2a0071 100644 --- a/configs/open5gs/mme.yaml.in +++ b/configs/open5gs/mme.yaml.in @@ -164,8 +164,9 @@ mme: ################################################################################ # o MSC/VLR # sgsap: -# server: -# - address: 127.0.0.2 +# client: +# - address: msc.open5gs.org # SCTP server address configured on the MSC/VLR +# local_address: 127.0.0.2 # SCTP local IP addresses to be bound in the MME # map: # tai: # plmn_id: @@ -188,7 +189,15 @@ mme: # mcc: 002 # mnc: 02 # lac: 43692 -# - address: msc.open5gs.org +# - address: # SCTP server address configured on the MSC/VLR +# - 127.0.0.88 +# - 10.0.0.88 +# - 172.16.0.88 +# - 2001:db8:babe::88 +# local_address: # SCTP local IP addresses to be bound in the MME +# - 127.0.0.2 +# - 192.168.1.4 +# - 2001:db8:cafe::2 # map: # tai: # plmn_id: diff --git a/configs/open5gs/nrf.yaml.in b/configs/open5gs/nrf.yaml.in index e082c0fb8..c69f8c40c 100644 --- a/configs/open5gs/nrf.yaml.in +++ b/configs/open5gs/nrf.yaml.in @@ -21,18 +21,31 @@ nrf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-nrf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-nrf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: nrf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.10 and advertise as open5gs-nrf.svc.local +# sbi: +# server: +# - address: 127.0.0.10 +# port: 7777 +# advertise: open5gs-nrf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.10 +# port: 7777 +# advertise: open5gs-nrf.svc.local:8888 # ################################################################################ # HTTPS scheme with TLS @@ -51,6 +64,24 @@ nrf: # server: # - address: nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/nrf.key +# cert: @sysconfdir@/open5gs/tls/nrf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/nrf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/nrf-client-sslkeylog.log +# sbi: +# server: +# - address: nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/nssf.yaml.in b/configs/open5gs/nssf.yaml.in index 258ff7825..015085f56 100644 --- a/configs/open5gs/nssf.yaml.in +++ b/configs/open5gs/nssf.yaml.in @@ -25,18 +25,31 @@ nssf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-nssf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-nssf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: nssf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.14 and advertise as open5gs-nssf.svc.local +# sbi: +# server: +# - address: 127.0.0.14 +# port: 7777 +# advertise: open5gs-nssf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.14 +# port: 7777 +# advertise: open5gs-nssf.svc.local:8888 # ################################################################################ # SBI Client @@ -64,27 +77,55 @@ nssf: # sst: 1 # sd: 009000 # -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation +# # ################################################################################ # HTTPS scheme with TLS @@ -110,6 +151,31 @@ nssf: # s_nssai: # sst: 1 # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/nssf.key +# cert: @sysconfdir@/open5gs/tls/nssf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/nssf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/nssf-client-sslkeylog.log +# sbi: +# server: +# - address: nssf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# nsi: +# - uri: https://nrf.localdomain +# s_nssai: +# sst: 1 +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/pcf.yaml.in b/configs/open5gs/pcf.yaml.in index afe96458b..10fd43faf 100644 --- a/configs/open5gs/pcf.yaml.in +++ b/configs/open5gs/pcf.yaml.in @@ -148,43 +148,83 @@ pcf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-pcf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-pcf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: pcf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.13 and advertise as open5gs-pcf.svc.local +# sbi: +# server: +# - address: 127.0.0.13 +# port: 7777 +# advertise: open5gs-pcf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.13 +# port: 7777 +# advertise: open5gs-pcf.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -206,6 +246,27 @@ pcf: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/pcf.key +# cert: @sysconfdir@/open5gs/tls/pcf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/pcf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/pcf-client-sslkeylog.log +# sbi: +# server: +# - address: pcf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/scp.yaml.in b/configs/open5gs/scp.yaml.in index 3d80497eb..b2d4795d0 100644 --- a/configs/open5gs/scp.yaml.in +++ b/configs/open5gs/scp.yaml.in @@ -63,28 +63,78 @@ scp: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-scp.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-scp.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: scp.localdomain +# port: 7777 +# +# o Bind to 127.0.0.200 and advertise as open5gs-scp.svc.local +# sbi: +# server: +# - address: 127.0.0.200 +# port: 7777 +# advertise: open5gs-scp.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.200 +# port: 7777 +# advertise: open5gs-scp.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # +# o Indirect Communication by Delegating to Next-SCP +# sbi: +# client: +# scp: +# - uri: http://127.0.0.200:7777 +# +# o Indirect Communication without Delegation +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegation +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the Next-SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation +# ################################################################################ # HTTPS scheme with TLS ################################################################################ @@ -105,6 +155,27 @@ scp: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/scp.key +# cert: @sysconfdir@/open5gs/tls/scp.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/scp-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/scp-client-sslkeylog.log +# sbi: +# server: +# - address: scp.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/sepp1.yaml.in b/configs/open5gs/sepp1.yaml.in index afa276a35..46d774ca5 100644 --- a/configs/open5gs/sepp1.yaml.in +++ b/configs/open5gs/sepp1.yaml.in @@ -148,6 +148,36 @@ sepp: # uri: https://sepp2.localdomain # resolve: 127.0.2.251 # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# private_key: @sysconfdir@/open5gs/tls/sepp1.key +# cert: @sysconfdir@/open5gs/tls/sepp1.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp1-server-sslkeylog.log +# client: +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp1-client-sslkeylog.log +# sbi: +# server: +# - address: 127.0.1.250 +# port: 7777 +# client: +# scp: +# - uri: http://127.0.0.200:7777 +# n32: +# server: +# - sender: sepp1.localdomain +# scheme: https +# address: 127.0.1.251 +# client: +# sepp: +# - receiver: sepp2.localdomain +# uri: https://sepp2.localdomain +# resolve: 127.0.2.251 +# # o Add client TLS verification to N32 interface # default: # tls: diff --git a/configs/open5gs/sepp2.yaml.in b/configs/open5gs/sepp2.yaml.in index fc78fb256..2b67f3f35 100644 --- a/configs/open5gs/sepp2.yaml.in +++ b/configs/open5gs/sepp2.yaml.in @@ -14,8 +14,10 @@ sepp: server: private_key: @sysconfdir@/open5gs/tls/sepp2.key cert: @sysconfdir@/open5gs/tls/sepp2.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp2-server-sslkeylog.log client: cacert: @sysconfdir@/open5gs/tls/ca.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp2-client-sslkeylog.log sbi: server: - address: 127.0.2.250 @@ -148,6 +150,36 @@ sepp: # uri: https://sepp1.localdomain # resolve: 127.0.1.251 # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# private_key: @sysconfdir@/open5gs/tls/sepp2.key +# cert: @sysconfdir@/open5gs/tls/sepp2.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp2-server-sslkeylog.log +# client: +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/sepp2-client-sslkeylog.log +# sbi: +# server: +# - address: 127.0.2.250 +# port: 7777 +# client: +# scp: +# - uri: http://127.0.0.200:7777 +# n32: +# server: +# - sender: sepp2.localdomain +# scheme: https +# address: 127.0.2.251 +# client: +# sepp: +# - receiver: sepp1.localdomain +# uri: https://sepp1.localdomain +# resolve: 127.0.1.251 +# # o Add client TLS verification to N32 interface # default: # tls: diff --git a/configs/open5gs/smf.yaml.in b/configs/open5gs/smf.yaml.in index 3ec2fb648..e47752393 100644 --- a/configs/open5gs/smf.yaml.in +++ b/configs/open5gs/smf.yaml.in @@ -186,43 +186,83 @@ smf: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-smf.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-smf.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: smf.localdomain +# port: 7777 +# +# o Bind to 127.0.0.4 and advertise as open5gs-smf.svc.local +# sbi: +# server: +# - address: 127.0.0.4 +# port: 7777 +# advertise: open5gs-smf.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.4 +# port: 7777 +# advertise: open5gs-smf.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -244,6 +284,27 @@ smf: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/smf.key +# cert: @sysconfdir@/open5gs/tls/smf.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/smf-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/smf-client-sslkeylog.log +# sbi: +# server: +# - address: smf.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/udm.yaml.in b/configs/open5gs/udm.yaml.in index a6a718094..395d041f6 100644 --- a/configs/open5gs/udm.yaml.in +++ b/configs/open5gs/udm.yaml.in @@ -38,7 +38,6 @@ udm: scp: - uri: http://127.0.0.200:7777 -# ################################################################################ # Home Network Public Key ################################################################################ @@ -82,43 +81,83 @@ udm: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-udm.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-udm.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: udm.localdomain +# port: 7777 +# +# o Bind to 127.0.0.12 and advertise as open5gs-udm.svc.local +# sbi: +# server: +# - address: 127.0.0.12 +# port: 7777 +# advertise: open5gs-udm.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.12 +# port: 7777 +# advertise: open5gs-udm.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -140,6 +179,27 @@ udm: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/udm.key +# cert: @sysconfdir@/open5gs/tls/udm.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/udm-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/udm-client-sslkeylog.log +# sbi: +# server: +# - address: udm.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/open5gs/udr.yaml.in b/configs/open5gs/udr.yaml.in index f8fd4250c..cfc41286c 100644 --- a/configs/open5gs/udr.yaml.in +++ b/configs/open5gs/udr.yaml.in @@ -23,43 +23,83 @@ udr: ################################################################################ # SBI Server ################################################################################ -# o Override SBI address to be advertised to NRF +# o Bind to the address on the eth0 and advertise as open5gs-udr.svc.local # sbi: # server: -# - dev: eth0 +# - dev:eth0 # advertise: open5gs-udr.svc.local # +# o Specify a custom port number 7777 while binding to the given address # sbi: # server: -# - address: localhost -# advertise: -# - 127.0.0.99 -# - ::1 +# - address: udr.localdomain +# port: 7777 +# +# o Bind to 127.0.0.20 and advertise as open5gs-udr.svc.local +# sbi: +# server: +# - address: 127.0.0.20 +# port: 7777 +# advertise: open5gs-udr.svc.local +# +# o Bind to port 7777 but advertise with a different port number 8888 +# sbi: +# server: +# - address: 127.0.0.20 +# port: 7777 +# advertise: open5gs-udr.svc.local:8888 # ################################################################################ # SBI Client ################################################################################ -# o Direct communication with NRF interaction +# o Direct Communication with NRF # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # -# o Indirect communication with delegated discovery +# o Indirect Communication by Delegating to SCP # sbi: # client: # scp: # - uri: http://127.0.0.200:7777 # -# o Indirect communication without delegated discovery +# o Indirect Communication without Delegation # sbi: # client: # nrf: # - uri: http://127.0.0.10:7777 # scp: # - uri: http://127.0.0.200:7777 -# discovery: -# delegated: no +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: no # Directly communicate NRF discovery +# scp: +# next: no # Do not delegate to SCP for next-hop +# +# o Indirect Communication with Delegated Discovery +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# delegated: +# nrf: +# nfm: no # Directly communicate NRF management functions +# disc: yes # Delegate discovery to SCP +# scp: +# next: yes # Delegate to SCP for next-hop communications +# +# o Default delegation: all communications are delegated to the SCP +# sbi: +# client: +# nrf: +# - uri: http://127.0.0.10:7777 +# scp: +# - uri: http://127.0.0.200:7777 +# # No 'delegated' section; defaults to AUTO delegation # ################################################################################ # HTTPS scheme with TLS @@ -81,6 +121,27 @@ udr: # nrf: # - uri: https://nrf.localdomain # +# o Enable SSL key logging for Wireshark +# - This configuration allows capturing SSL/TLS session keys +# for debugging or analysis purposes using Wireshark. +# default: +# tls: +# server: +# scheme: https +# private_key: @sysconfdir@/open5gs/tls/udr.key +# cert: @sysconfdir@/open5gs/tls/udr.crt +# sslkeylogfile: @localstatedir@/log/open5gs/tls/udr-server-sslkeylog.log +# client: +# scheme: https +# cacert: @sysconfdir@/open5gs/tls/ca.crt +# client_sslkeylogfile: @localstatedir@/log/open5gs/tls/udr-client-sslkeylog.log +# sbi: +# server: +# - address: udr.localdomain +# client: +# nrf: +# - uri: https://nrf.localdomain +# # o Add client TLS verification # default: # tls: diff --git a/configs/srsenb.yaml.in b/configs/srsenb.yaml.in index a30bbf520..9f2185dcd 100644 --- a/configs/srsenb.yaml.in +++ b/configs/srsenb.yaml.in @@ -67,7 +67,7 @@ mme: tai: - plmn_id: mcc: 901 - mnc: 70 + mnc: 70 tac: 7 security: integrity_order : [ EIA2, EIA1, EIA0 ] diff --git a/debian/control b/debian/control index 8cb84efbd..d8c28b9ea 100644 --- a/debian/control +++ b/debian/control @@ -13,7 +13,7 @@ Build-Depends: debhelper (>= 11), libgnutls28-dev, libgcrypt-dev, libssl-dev, - libidn11-dev, + libidn-dev | libidn11-dev, libmongoc-dev, libbson-dev, libsctp-dev, diff --git a/debian/open5gs-common.dirs b/debian/open5gs-common.dirs index d5b197ccf..be7656f72 100644 --- a/debian/open5gs-common.dirs +++ b/debian/open5gs-common.dirs @@ -1 +1 @@ -var/log/open5gs +var/log/open5gs/tls diff --git a/docker/debian/latest/base/Dockerfile b/docker/debian/latest/base/Dockerfile index 072628d16..bac24f0b5 100644 --- a/docker/debian/latest/base/Dockerfile +++ b/docker/debian/latest/base/Dockerfile @@ -22,7 +22,6 @@ RUN apt-get update && \ libgnutls28-dev \ libgcrypt-dev \ libssl-dev \ - libidn11-dev \ libmongoc-dev \ libbson-dev \ libyaml-dev \ @@ -35,4 +34,9 @@ RUN apt-get update && \ ca-certificates \ netbase \ pkg-config && \ - apt-get clean + if apt-cache show libidn-dev > /dev/null 2>&1; then \ + apt-get install -y --no-install-recommends libidn-dev; \ + else \ + apt-get install -y --no-install-recommends libidn11-dev; \ + fi && \ + apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/docker/ubuntu/latest/base/Dockerfile b/docker/ubuntu/latest/base/Dockerfile index 072628d16..bac24f0b5 100644 --- a/docker/ubuntu/latest/base/Dockerfile +++ b/docker/ubuntu/latest/base/Dockerfile @@ -22,7 +22,6 @@ RUN apt-get update && \ libgnutls28-dev \ libgcrypt-dev \ libssl-dev \ - libidn11-dev \ libmongoc-dev \ libbson-dev \ libyaml-dev \ @@ -35,4 +34,9 @@ RUN apt-get update && \ ca-certificates \ netbase \ pkg-config && \ - apt-get clean + if apt-cache show libidn-dev > /dev/null 2>&1; then \ + apt-get install -y --no-install-recommends libidn-dev; \ + else \ + apt-get install -y --no-install-recommends libidn11-dev; \ + fi && \ + apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/docs/_docs/guide/02-building-open5gs-from-sources.md b/docs/_docs/guide/02-building-open5gs-from-sources.md index e22fdc7a5..01e572f6e 100644 --- a/docs/_docs/guide/02-building-open5gs-from-sources.md +++ b/docs/_docs/guide/02-building-open5gs-from-sources.md @@ -61,7 +61,7 @@ $ sudo ip link set ogstun up Install the dependencies for building the source code. ```bash -$ sudo apt install python3-pip python3-setuptools python3-wheel ninja-build build-essential flex bison git cmake libsctp-dev libgnutls28-dev libgcrypt-dev libssl-dev libidn11-dev libmongoc-dev libbson-dev libyaml-dev libnghttp2-dev libmicrohttpd-dev libcurl4-gnutls-dev libnghttp2-dev libtins-dev libtalloc-dev meson +$ sudo apt install python3-pip python3-setuptools python3-wheel ninja-build build-essential flex bison git cmake libsctp-dev libgnutls28-dev libgcrypt-dev libssl-dev libidn-dev libmongoc-dev libbson-dev libyaml-dev libnghttp2-dev libmicrohttpd-dev libcurl4-gnutls-dev libnghttp2-dev libtins-dev libtalloc-dev meson ``` Git clone. @@ -447,7 +447,7 @@ $ cp open5gs* /usr/bin/ For convenience, you can execute all NFs at once by using the following command. ```bash $ ./build/tests/app/5gc ## 5G Core Only with ./build/configs/sample.yaml -$ ./build/tests/app/epc -c ./build/configs/srslte.yaml ## EPC Only with ./build/configs/srslte.yaml +$ ./build/tests/app/epc -c ./build/configs/srsenb.yaml ## EPC Only with ./build/configs/srsenb.yaml $ ./build/tests/app/app ## Both 5G Core and EPC with ./build/configs/sample.yaml ``` diff --git a/docs/_docs/troubleshoot/02-now-in-github-issues.md b/docs/_docs/troubleshoot/02-now-in-github-issues.md index 06b26c352..11b1b84fc 100644 --- a/docs/_docs/troubleshoot/02-now-in-github-issues.md +++ b/docs/_docs/troubleshoot/02-now-in-github-issues.md @@ -1356,7 +1356,7 @@ $ DIST=debian TAG=stretch docker-compose run dev ```bash $ sudo dpkg --add-architecture armel $ sudo apt update -$ sudo apt install libsctp-dev:armel libyaml-dev:armel libgnutls28-dev:armel libgcrypt-dev:armel libidn11-dev:armel libssl-dev:armel libmongoc-dev:armel libbson-dev:armel +$ sudo apt install libsctp-dev:armel libyaml-dev:armel libgnutls28-dev:armel libgcrypt-dev:armel libidn-dev:armel libssl-dev:armel libmongoc-dev:armel libbson-dev:armel $ sudo apt install crossbuild-essential-armel $ sudo apt install qemu $ git clone https://github.com/{{ site.github_username }}/open5gs diff --git a/docs/_pages/docs.md b/docs/_pages/docs.md index 350ef50ff..65d3b364a 100644 --- a/docs/_pages/docs.md +++ b/docs/_pages/docs.md @@ -20,7 +20,7 @@ head_inline: "" - In the lab - [A Demonstration of 30 Gbps Load Testing for Accelerated UPF with Open5gs](https://nextepc.com/technology) - - [Measurement of UPF Performance](https://github.com/s5uishida/simple_measurement_of_upf_performance) + - [Measurement of UPF Performance](https://github.com/s5uishida/sample_config_misc_for_mobile_network#performance_measurement) - Troubleshooting - [Simple Issues](troubleshoot/01-simple-issues) @@ -43,6 +43,7 @@ head_inline: "" - [SMF Code Explanation](https://medium.com/@aditya.koranga/open5gs-smf-code-explanation-with-flow-charts-a3b3cd38c991) - @infinitydon + - [OAI's O-RAN Integration With Open5gs 5G Core](https://futuredon.medium.com/integrating-disaggregated-openairinterface-o-ran-components-with-open5gs-5g-core-76e5deac1730) - [Open5GS on Amazon Elastic Kubernetes Service](https://aws.amazon.com/blogs/opensource/open-source-mobile-core-network-implementation-on-amazon-elastic-kubernetes-service/) - [Kubernetes Open5GS Deployment](https://dev.to/infinitydon/virtual-4g-simulation-using-kubernetes-and-gns3-3b7k?fbclid=IwAR1p99h13a-mCfejanbBQe0H0-jp5grXkn5mWf1WrTHf47UtegB2-UHGGZQ) - [5G Core SBI mTLS Using External Certificate PKI](https://futuredon.medium.com/5g-core-sbi-mtls-using-external-certificate-pki-4ffc02ac7728) diff --git a/lib/app/ogs-config.c b/lib/app/ogs-config.c index 01cfa1eb2..395712c80 100644 --- a/lib/app/ogs-config.c +++ b/lib/app/ogs-config.c @@ -247,6 +247,12 @@ int ogs_app_parse_global_conf(ogs_yaml_iter_t *parent) } else if (!strcmp(parameter_key, "use_openair")) { global_conf.parameter.use_openair = ogs_yaml_iter_bool(¶meter_iter); + } else if (!strcmp(parameter_key, "use_upg_vpp")) { + global_conf.parameter.use_upg_vpp = + ogs_yaml_iter_bool(¶meter_iter); + } else if (!strcmp(parameter_key, "fake_csfb")) { + global_conf.parameter.fake_csfb = + ogs_yaml_iter_bool(¶meter_iter); } else if (!strcmp(parameter_key, "no_ipv4v6_local_addr_in_packet_filter")) { global_conf.parameter. @@ -1252,7 +1258,6 @@ ogs_app_slice_conf_t *ogs_app_slice_conf_add( ogs_assert(policy_conf); ogs_assert(s_nssai); - ogs_assert(s_nssai->sst); ogs_pool_alloc(&slice_conf_pool, &slice_conf); if (!slice_conf) { @@ -1283,7 +1288,6 @@ ogs_app_slice_conf_t *ogs_app_slice_conf_find_by_s_nssai( ogs_assert(policy_conf); ogs_assert(s_nssai); - ogs_assert(s_nssai->sst); ogs_list_for_each(&policy_conf->slice_list, slice_conf) { if (slice_conf->data.s_nssai.sst == s_nssai->sst && diff --git a/lib/app/ogs-config.h b/lib/app/ogs-config.h index 2086d9b98..6f98a7c66 100644 --- a/lib/app/ogs-config.h +++ b/lib/app/ogs-config.h @@ -69,6 +69,8 @@ typedef struct ogs_global_conf_s { int multicast; int use_openair; + int fake_csfb; + int use_upg_vpp; int no_ipv4v6_local_addr_in_packet_filter; int no_pfcp_rr_select; diff --git a/lib/core/ogs-sockaddr.c b/lib/core/ogs-sockaddr.c index fb8dbeb8c..61ad459db 100644 --- a/lib/core/ogs-sockaddr.c +++ b/lib/core/ogs-sockaddr.c @@ -55,6 +55,10 @@ #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __ogs_sock_domain +static bool ogs_sockaddr_compare(const ogs_sockaddr_t *a, + const ogs_sockaddr_t *b, + bool compare_port); + /* If you want to use getnameinfo, * you need to consider DNS query delay (about 10 seconds) */ #if 0 @@ -264,6 +268,60 @@ int ogs_sortaddrinfo(ogs_sockaddr_t **sa_list, int family) return OGS_OK; } +/*-------------------------------------------------------------------------- + * Merge a single node if not already in "dest" list + *-------------------------------------------------------------------------- + */ +void ogs_merge_single_addrinfo( + ogs_sockaddr_t **dest, const ogs_sockaddr_t *item) +{ + ogs_sockaddr_t *p; + ogs_sockaddr_t *new_sa; + + ogs_assert(dest); + ogs_assert(item); + + p = *dest; + + while (p) { + if (ogs_sockaddr_is_equal(p, item)) { + /* Already exists */ + return; + } + p = p->next; + } + new_sa = (ogs_sockaddr_t *)ogs_malloc(sizeof(*new_sa)); + ogs_assert(new_sa); + memcpy(new_sa, item, sizeof(*new_sa)); + if (item->hostname) { + new_sa->hostname = ogs_strdup(item->hostname); + ogs_assert(new_sa->hostname); + } + new_sa->next = NULL; + if (!(*dest)) { + *dest = new_sa; + } else { + p = *dest; + while (p->next) + p = p->next; + p->next = new_sa; + } +} + +/*-------------------------------------------------------------------------- + * Merge an entire src list into dest + *-------------------------------------------------------------------------- + */ +void ogs_merge_addrinfo(ogs_sockaddr_t **dest, const ogs_sockaddr_t *src) +{ + const ogs_sockaddr_t *cur; + cur = src; + while (cur) { + ogs_merge_single_addrinfo(dest, cur); + cur = cur->next; + } +} + ogs_sockaddr_t *ogs_link_local_addr(const char *dev, const ogs_sockaddr_t *sa) { #if defined(HAVE_GETIFADDRS) @@ -419,13 +477,16 @@ socklen_t ogs_sockaddr_len(const void *sa) } } -bool ogs_sockaddr_is_equal(const void *p, const void *q) +/* + * Helper function to compare two addresses. + * If compare_port is true, compare both port and address. + * Otherwise, compare address only. + */ +static bool ogs_sockaddr_compare(const ogs_sockaddr_t *a, + const ogs_sockaddr_t *b, + bool compare_port) { - const ogs_sockaddr_t *a, *b; - - a = p; ogs_assert(a); - b = q; ogs_assert(b); if (a->ogs_sa_family != b->ogs_sa_family) @@ -433,23 +494,68 @@ bool ogs_sockaddr_is_equal(const void *p, const void *q) switch (a->ogs_sa_family) { case AF_INET: - if (a->sin.sin_port != b->sin.sin_port) + if (compare_port && (a->sin.sin_port != b->sin.sin_port)) return false; - if (memcmp(&a->sin.sin_addr, &b->sin.sin_addr, sizeof(struct in_addr)) != 0) + if (memcmp(&a->sin.sin_addr, &b->sin.sin_addr, + sizeof(struct in_addr)) != 0) return false; return true; case AF_INET6: - if (a->sin6.sin6_port != b->sin6.sin6_port) + if (compare_port && (a->sin6.sin6_port != b->sin6.sin6_port)) return false; - if (memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, sizeof(struct in6_addr)) != 0) + if (memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, + sizeof(struct in6_addr)) != 0) return false; return true; default: - ogs_error("Unexpected address faimily %u", a->ogs_sa_family); + ogs_error("Unexpected address family %u", a->ogs_sa_family); ogs_abort(); + return false; /* Defensive return */ } } +/* Compare addresses including port */ +bool ogs_sockaddr_is_equal(const void *p, const void *q) +{ + const ogs_sockaddr_t *a = (const ogs_sockaddr_t *)p; + const ogs_sockaddr_t *b = (const ogs_sockaddr_t *)q; + return ogs_sockaddr_compare(a, b, true); +} + +/* Compare addresses without considering port */ +bool ogs_sockaddr_is_equal_addr(const void *p, const void *q) +{ + const ogs_sockaddr_t *a = (const ogs_sockaddr_t *)p; + const ogs_sockaddr_t *b = (const ogs_sockaddr_t *)q; + return ogs_sockaddr_compare(a, b, false); +} + +bool ogs_sockaddr_check_any_match( + ogs_sockaddr_t *base, + ogs_sockaddr_t *list, const ogs_sockaddr_t *single, bool compare_port) +{ + ogs_sockaddr_t *p = NULL; + + while (list) { + p = base; + while (p) { + if (ogs_sockaddr_compare(p, list, compare_port) == true) + return true; + p = p->next; + } + list = list->next; + } + if (single) { + p = base; + while (p) { + if (ogs_sockaddr_compare(p, single, compare_port) == true) + return true; + p = p->next; + } + } + return false; +} + static int parse_network(ogs_ipsubnet_t *ipsub, const char *network) { /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ @@ -666,3 +772,31 @@ char *ogs_ipstrdup(ogs_sockaddr_t *addr) return ogs_strdup(buf); } + +char *ogs_sockaddr_to_string_static(ogs_sockaddr_t *sa_list) +{ + static char dumpstr[OGS_HUGE_LEN] = { 0, }; + char *p, *last; + ogs_sockaddr_t *addr = NULL; + + last = dumpstr + OGS_HUGE_LEN; + p = dumpstr; + + addr = (ogs_sockaddr_t *)sa_list; + while (addr) { + char buf[OGS_ADDRSTRLEN]; + p = ogs_slprintf(p, last, "[%s]:%d ", + OGS_ADDR(addr, buf), OGS_PORT(addr)); + addr = addr->next; + } + + if (p > dumpstr) { + /* If there is more than one addr, remove the last character */ + *(p-1) = 0; + + return dumpstr; + } + + /* No address */ + return NULL; +} diff --git a/lib/core/ogs-sockaddr.h b/lib/core/ogs-sockaddr.h index a28e5b570..144255926 100644 --- a/lib/core/ogs-sockaddr.h +++ b/lib/core/ogs-sockaddr.h @@ -67,20 +67,8 @@ struct ogs_sockaddr_s { * If there is a name in the configuration file, * it is set in the 'hostname' of ogs_sockaddr_t. * Then, it immediately call getaddrinfo() to fill addr in ogs_sockaddr_t. - * - * When it was always possible to convert DNS to addr, that was no problem. - * However, in some environments, such as Roaming, there are situations - * where it is difficult to always change the DNS to addr. - * - * So, 'fqdn' was created for the purpose of first use in ogs_sbi_client_t. - * 'fqdn' always do not change with addr. - * This value is used as it is in the actual client connection. - * - * Note that 'hostname' is still in use for server or other client - * except for ogs_sbi_client_t. */ char *hostname; - char *fqdn; ogs_sockaddr_t *next; }; @@ -103,6 +91,10 @@ int ogs_copyaddrinfo( int ogs_filteraddrinfo(ogs_sockaddr_t **sa_list, int family); int ogs_sortaddrinfo(ogs_sockaddr_t **sa_list, int family); +void ogs_merge_single_addrinfo( + ogs_sockaddr_t **dest, const ogs_sockaddr_t *item); +void ogs_merge_addrinfo(ogs_sockaddr_t **dest, const ogs_sockaddr_t *src); + ogs_sockaddr_t *ogs_link_local_addr(const char *dev, const ogs_sockaddr_t *sa); ogs_sockaddr_t *ogs_link_local_addr_by_dev(const char *dev); ogs_sockaddr_t *ogs_link_local_addr_by_sa(const ogs_sockaddr_t *sa); @@ -119,12 +111,18 @@ int ogs_inet_pton(int family, const char *src, void *sa); socklen_t ogs_sockaddr_len(const void *sa); bool ogs_sockaddr_is_equal(const void *p, const void *q); +bool ogs_sockaddr_is_equal_addr(const void *p, const void *q); + +bool ogs_sockaddr_check_any_match( + ogs_sockaddr_t *base, + ogs_sockaddr_t *list, const ogs_sockaddr_t *single, bool compare_port); int ogs_ipsubnet(ogs_ipsubnet_t *ipsub, const char *ipstr, const char *mask_or_numbits); char *ogs_gethostname(ogs_sockaddr_t *addr); char *ogs_ipstrdup(ogs_sockaddr_t *addr); +char *ogs_sockaddr_to_string_static(ogs_sockaddr_t *sa_list); #ifdef __cplusplus } diff --git a/lib/dbi/session.c b/lib/dbi/session.c index ee1fa5f6a..5ebc7822d 100644 --- a/lib/dbi/session.c +++ b/lib/dbi/session.c @@ -85,6 +85,7 @@ int ogs_dbi_session_data(char *supi, ogs_s_nssai_t *s_nssai, char *dnn, if (!strcmp(key, OGS_SLICE_STRING) && BSON_ITER_HOLDS_ARRAY(&iter)) { bson_iter_recurse(&iter, &child1_iter); while (bson_iter_next(&child1_iter)) { + bool sst_presence = false; uint8_t sst; ogs_uint24_t sd; @@ -97,6 +98,7 @@ int ogs_dbi_session_data(char *supi, ogs_s_nssai_t *s_nssai, char *dnn, if (!strcmp(child2_key, OGS_SST_STRING) && BSON_ITER_HOLDS_INT32(&child2_iter)) { + sst_presence = true; sst = bson_iter_int32(&child2_iter); } else if (!strcmp(child2_key, OGS_SD_STRING) && BSON_ITER_HOLDS_UTF8(&child2_iter)) { @@ -109,7 +111,7 @@ int ogs_dbi_session_data(char *supi, ogs_s_nssai_t *s_nssai, char *dnn, } } - if (!sst) { + if (!sst_presence) { ogs_error("No SST"); continue; } diff --git a/lib/dbi/subscription.c b/lib/dbi/subscription.c index 0f5ed89f2..6799a0c56 100644 --- a/lib/dbi/subscription.c +++ b/lib/dbi/subscription.c @@ -39,9 +39,16 @@ int ogs_dbi_auth_info(char *supi, ogs_dbi_auth_info_t *auth_info) ogs_assert(auth_info); supi_type = ogs_id_get_type(supi); - ogs_assert(supi_type); + if (!supi_type) { + ogs_error("Invalid supi=%s", supi); + return OGS_ERROR; + } supi_id = ogs_id_get_value(supi); - ogs_assert(supi_id); + if (!supi_id) { + ogs_error("Invalid supi=%s", supi); + ogs_free(supi_type); + return OGS_ERROR; + } query = BCON_NEW(supi_type, BCON_UTF8(supi_id)); #if MONGOC_CHECK_VERSION(1, 5, 0) @@ -459,6 +466,7 @@ int ogs_dbi_subscription_data(char *supi, bson_iter_recurse(&iter, &child1_iter); while (bson_iter_next(&child1_iter)) { ogs_slice_data_t *slice_data = NULL; + bool sst_presence = false; ogs_assert( subscription_data->num_of_slice < OGS_MAX_NUM_OF_SLICE); @@ -476,6 +484,7 @@ int ogs_dbi_subscription_data(char *supi, if (!strcmp(child2_key, OGS_SST_STRING) && BSON_ITER_HOLDS_INT32(&child2_iter)) { slice_data->s_nssai.sst = bson_iter_int32(&child2_iter); + sst_presence = true; } else if (!strcmp(child2_key, OGS_SD_STRING) && BSON_ITER_HOLDS_UTF8(&child2_iter)) { utf8 = bson_iter_utf8(&child2_iter, &length); @@ -792,6 +801,12 @@ int ogs_dbi_subscription_data(char *supi, } } } + + if (!sst_presence) { + ogs_error("No SST"); + continue; + } + subscription_data->num_of_slice++; } } else if (!strcmp(key, OGS_MME_HOST_STRING) && diff --git a/lib/diameter/common/base.h b/lib/diameter/common/base.h index a44dece72..d8ad7f77a 100644 --- a/lib/diameter/common/base.h +++ b/lib/diameter/common/base.h @@ -90,7 +90,7 @@ int ogs_diam_start(void); void ogs_diam_final(void); int ogs_diam_config_init(ogs_diam_config_t *fd_config); -bool ogs_diam_app_connected(uint32_t app_id); +bool ogs_diam_is_relay_or_app_advertised(uint32_t app_id); int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp ); diff --git a/lib/diameter/common/util.c b/lib/diameter/common/util.c index fa534c4b8..94a7fb8ee 100644 --- a/lib/diameter/common/util.c +++ b/lib/diameter/common/util.c @@ -19,7 +19,7 @@ #include "ogs-diameter-common.h" -bool ogs_diam_app_connected(uint32_t app_id) +bool ogs_diam_is_relay_or_app_advertised(uint32_t app_id) { struct fd_list *li = NULL; struct fd_app *found = NULL; @@ -36,18 +36,23 @@ bool ogs_diam_app_connected(uint32_t app_id) if (state == STATE_OPEN) { ogs_debug("'%s' STATE is OPEN", p->info.pi_diamid); - /* Check if the remote peer advertised the message's appli */ - fd_app_check(&p->info.runtime.pir_apps, app_id, &found); - - if (found) break; + if (p->info.runtime.pir_relay) { + ogs_debug("'%s' RELAY is enabled", p->info.pi_diamid); + CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); + return true; + } else { + /* Check if the remote peer advertised the message's appli */ + fd_app_check(&p->info.runtime.pir_apps, app_id, &found); + if (found) { + CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); + return true; + } + } } else { ogs_debug("'%s' STATE[%d] is NOT open ", p->info.pi_diamid, state); } } CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); - if (found) - return true; - else - return false; + return false; } diff --git a/lib/gtp/context.c b/lib/gtp/context.c index 17620b4da..5c144b54f 100644 --- a/lib/gtp/context.c +++ b/lib/gtp/context.c @@ -200,6 +200,7 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) server_key); } + /* Add address information */ addr = NULL; for (i = 0; i < num; i++) { rv = ogs_addaddrinfo(&addr, @@ -207,17 +208,30 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) ogs_assert(rv == OGS_OK); } + /* Add each address as a separate socknode */ if (addr) { - if (ogs_global_conf()->parameter. - no_ipv4 == 0) - ogs_socknode_add( - &self.gtpc_list, AF_INET, addr, - is_option ? &option : NULL); - if (ogs_global_conf()->parameter. - no_ipv6 == 0) - ogs_socknode_add( - &self.gtpc_list6, AF_INET6, addr, - is_option ? &option : NULL); + ogs_sockaddr_t *current = addr; + while (current) { + if (current->ogs_sa_family == + AF_INET && + ogs_global_conf()-> + parameter.no_ipv4 == 0) { + ogs_socknode_add(&self.gtpc_list, + AF_INET, current, + is_option ? + &option : NULL); + } + if (current->ogs_sa_family == + AF_INET6 && + ogs_global_conf()-> + parameter.no_ipv6 == 0) { + ogs_socknode_add(&self.gtpc_list6, + AF_INET6, current, + is_option ? + &option : NULL); + } + current = current->next; + } ogs_freeaddrinfo(addr); } @@ -417,16 +431,28 @@ int ogs_gtp_context_parse_config(const char *local, const char *remote) ogs_list_init(&list6); if (addr) { - if (ogs_global_conf()->parameter. - no_ipv4 == 0) - ogs_socknode_add( - &list, AF_INET, addr, - is_option ? &option : NULL); - if (ogs_global_conf()->parameter. - no_ipv6 == 0) - ogs_socknode_add( - &list6, AF_INET6, addr, - is_option ? &option : NULL); + ogs_sockaddr_t *current = addr; + while (current) { + if (current->ogs_sa_family == + AF_INET && + ogs_global_conf()-> + parameter.no_ipv4 == 0) { + ogs_socknode_add(&list, + AF_INET, current, + is_option ? + &option : NULL); + } + if (current->ogs_sa_family == + AF_INET6 && + ogs_global_conf()-> + parameter.no_ipv6 == 0) { + ogs_socknode_add(&list6, + AF_INET6, current, + is_option ? + &option : NULL); + } + current = current->next; + } ogs_freeaddrinfo(addr); } diff --git a/lib/nas/5gs/ies.c b/lib/nas/5gs/ies.c index 79d78117e..5c39a9eff 100644 --- a/lib/nas/5gs/ies.c +++ b/lib/nas/5gs/ies.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2024-01-21 18:47:47.812038 by acetcom + * Created on: 2024-12-11 21:13:08.097860 by acetcom * from 24501-h90.docx ******************************************************************************/ @@ -48,7 +48,14 @@ int ogs_nas_5gs_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) int ogs_nas_5gs_decode_additional_information(ogs_nas_additional_information_t *additional_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_additional_information_t *source = (ogs_nas_additional_information_t *)pkbuf->data; + ogs_nas_additional_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_additional_information_t *)pkbuf->data; additional_information->length = source->length; size = additional_information->length + sizeof(additional_information->length); @@ -87,7 +94,14 @@ int ogs_nas_5gs_encode_additional_information(ogs_pkbuf_t *pkbuf, ogs_nas_additi int ogs_nas_5gs_decode_service_level_aa_container(ogs_nas_service_level_aa_container_t *service_level_aa_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_service_level_aa_container_t *source = (ogs_nas_service_level_aa_container_t *)pkbuf->data; + ogs_nas_service_level_aa_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_service_level_aa_container_t *)pkbuf->data; service_level_aa_container->length = be16toh(source->length); size = service_level_aa_container->length + sizeof(service_level_aa_container->length); @@ -167,7 +181,14 @@ int ogs_nas_5gs_encode_access_type(ogs_pkbuf_t *pkbuf, ogs_nas_access_type_t *ac int ogs_nas_5gs_decode_dnn(ogs_nas_dnn_t *dnn, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_dnn_t *source = (ogs_nas_dnn_t *)pkbuf->data; + ogs_nas_dnn_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_dnn_t *)pkbuf->data; dnn->length = source->length; size = dnn->length + sizeof(dnn->length); @@ -219,7 +240,14 @@ int ogs_nas_5gs_encode_dnn(ogs_pkbuf_t *pkbuf, ogs_nas_dnn_t *dnn) int ogs_nas_5gs_decode_eap_message(ogs_nas_eap_message_t *eap_message, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eap_message_t *source = (ogs_nas_eap_message_t *)pkbuf->data; + ogs_nas_eap_message_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eap_message_t *)pkbuf->data; eap_message->length = be16toh(source->length); size = eap_message->length + sizeof(eap_message->length); @@ -299,7 +327,14 @@ int ogs_nas_5gs_encode_gprs_timer(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_t *gprs int ogs_nas_5gs_decode_gprs_timer_2(ogs_nas_gprs_timer_2_t *gprs_timer_2, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_gprs_timer_2_t *source = (ogs_nas_gprs_timer_2_t *)pkbuf->data; + ogs_nas_gprs_timer_2_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_gprs_timer_2_t *)pkbuf->data; gprs_timer_2->length = source->length; size = gprs_timer_2->length + sizeof(gprs_timer_2->length); @@ -338,7 +373,14 @@ int ogs_nas_5gs_encode_gprs_timer_2(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_2_t * int ogs_nas_5gs_decode_gprs_timer_3(ogs_nas_gprs_timer_3_t *gprs_timer_3, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_gprs_timer_3_t *source = (ogs_nas_gprs_timer_3_t *)pkbuf->data; + ogs_nas_gprs_timer_3_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_gprs_timer_3_t *)pkbuf->data; gprs_timer_3->length = source->length; size = gprs_timer_3->length + sizeof(gprs_timer_3->length); @@ -377,7 +419,14 @@ int ogs_nas_5gs_encode_gprs_timer_3(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_3_t * int ogs_nas_5gs_decode_s_nssai(ogs_nas_s_nssai_t *s_nssai, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_s_nssai_t *source = (ogs_nas_s_nssai_t *)pkbuf->data; + ogs_nas_s_nssai_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_s_nssai_t *)pkbuf->data; s_nssai->length = source->length; size = s_nssai->length + sizeof(s_nssai->length); @@ -416,7 +465,14 @@ int ogs_nas_5gs_encode_s_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_s_nssai_t *s_nssai) int ogs_nas_5gs_decode_5gmm_capability(ogs_nas_5gmm_capability_t *gmm_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gmm_capability_t *source = (ogs_nas_5gmm_capability_t *)pkbuf->data; + ogs_nas_5gmm_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gmm_capability_t *)pkbuf->data; gmm_capability->length = source->length; size = gmm_capability->length + sizeof(gmm_capability->length); @@ -455,7 +511,14 @@ int ogs_nas_5gs_encode_5gmm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gmm_capabili int ogs_nas_5gs_decode_abba(ogs_nas_abba_t *abba, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_abba_t *source = (ogs_nas_abba_t *)pkbuf->data; + ogs_nas_abba_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_abba_t *)pkbuf->data; abba->length = source->length; size = abba->length + sizeof(abba->length); @@ -494,7 +557,14 @@ int ogs_nas_5gs_encode_abba(ogs_pkbuf_t *pkbuf, ogs_nas_abba_t *abba) int ogs_nas_5gs_decode_additional_5g_security_information(ogs_nas_additional_5g_security_information_t *additional_security_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_additional_5g_security_information_t *source = (ogs_nas_additional_5g_security_information_t *)pkbuf->data; + ogs_nas_additional_5g_security_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_additional_5g_security_information_t *)pkbuf->data; additional_security_information->length = source->length; size = additional_security_information->length + sizeof(additional_security_information->length); @@ -533,7 +603,14 @@ int ogs_nas_5gs_encode_additional_5g_security_information(ogs_pkbuf_t *pkbuf, og int ogs_nas_5gs_decode_additional_information_requested(ogs_nas_additional_information_requested_t *additional_information_requested, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_additional_information_requested_t *source = (ogs_nas_additional_information_requested_t *)pkbuf->data; + ogs_nas_additional_information_requested_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_additional_information_requested_t *)pkbuf->data; additional_information_requested->length = source->length; size = additional_information_requested->length + sizeof(additional_information_requested->length); @@ -572,7 +649,14 @@ int ogs_nas_5gs_encode_additional_information_requested(ogs_pkbuf_t *pkbuf, ogs_ int ogs_nas_5gs_decode_allowed_pdu_session_status(ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_allowed_pdu_session_status_t *source = (ogs_nas_allowed_pdu_session_status_t *)pkbuf->data; + ogs_nas_allowed_pdu_session_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_allowed_pdu_session_status_t *)pkbuf->data; allowed_pdu_session_status->length = source->length; size = allowed_pdu_session_status->length + sizeof(allowed_pdu_session_status->length); @@ -615,7 +699,14 @@ int ogs_nas_5gs_encode_allowed_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_al int ogs_nas_5gs_decode_authentication_failure_parameter(ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_failure_parameter_t *source = (ogs_nas_authentication_failure_parameter_t *)pkbuf->data; + ogs_nas_authentication_failure_parameter_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_failure_parameter_t *)pkbuf->data; authentication_failure_parameter->length = source->length; size = authentication_failure_parameter->length + sizeof(authentication_failure_parameter->length); @@ -654,7 +745,14 @@ int ogs_nas_5gs_encode_authentication_failure_parameter(ogs_pkbuf_t *pkbuf, ogs_ int ogs_nas_5gs_decode_authentication_parameter_autn(ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_parameter_autn_t *source = (ogs_nas_authentication_parameter_autn_t *)pkbuf->data; + ogs_nas_authentication_parameter_autn_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_parameter_autn_t *)pkbuf->data; authentication_parameter_autn->length = source->length; size = authentication_parameter_autn->length + sizeof(authentication_parameter_autn->length); @@ -727,7 +825,14 @@ int ogs_nas_5gs_encode_authentication_parameter_rand(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_5gs_decode_authentication_response_parameter(ogs_nas_authentication_response_parameter_t *authentication_response_parameter, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_response_parameter_t *source = (ogs_nas_authentication_response_parameter_t *)pkbuf->data; + ogs_nas_authentication_response_parameter_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_response_parameter_t *)pkbuf->data; authentication_response_parameter->length = source->length; size = authentication_response_parameter->length + sizeof(authentication_response_parameter->length); @@ -798,7 +903,14 @@ int ogs_nas_5gs_encode_configuration_update_indication(ogs_pkbuf_t *pkbuf, ogs_n int ogs_nas_5gs_decode_cag_information_list(ogs_nas_cag_information_list_t *cag_information_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_cag_information_list_t *source = (ogs_nas_cag_information_list_t *)pkbuf->data; + ogs_nas_cag_information_list_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_cag_information_list_t *)pkbuf->data; cag_information_list->length = be16toh(source->length); size = cag_information_list->length + sizeof(cag_information_list->length); @@ -844,7 +956,14 @@ int ogs_nas_5gs_encode_cag_information_list(ogs_pkbuf_t *pkbuf, ogs_nas_cag_info int ogs_nas_5gs_decode_ciphering_key_data(ogs_nas_ciphering_key_data_t *ciphering_key_data, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ciphering_key_data_t *source = (ogs_nas_ciphering_key_data_t *)pkbuf->data; + ogs_nas_ciphering_key_data_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ciphering_key_data_t *)pkbuf->data; ciphering_key_data->length = be16toh(source->length); size = ciphering_key_data->length + sizeof(ciphering_key_data->length); @@ -890,7 +1009,14 @@ int ogs_nas_5gs_encode_ciphering_key_data(ogs_pkbuf_t *pkbuf, ogs_nas_ciphering_ int ogs_nas_5gs_decode_daylight_saving_time(ogs_nas_daylight_saving_time_t *daylight_saving_time, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_daylight_saving_time_t *source = (ogs_nas_daylight_saving_time_t *)pkbuf->data; + ogs_nas_daylight_saving_time_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_daylight_saving_time_t *)pkbuf->data; daylight_saving_time->length = source->length; size = daylight_saving_time->length + sizeof(daylight_saving_time->length); @@ -997,7 +1123,14 @@ int ogs_nas_5gs_encode_de_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_de_regis int ogs_nas_5gs_decode_emergency_number_list(ogs_nas_emergency_number_list_t *emergency_number_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_emergency_number_list_t *source = (ogs_nas_emergency_number_list_t *)pkbuf->data; + ogs_nas_emergency_number_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_emergency_number_list_t *)pkbuf->data; emergency_number_list->length = source->length; size = emergency_number_list->length + sizeof(emergency_number_list->length); @@ -1036,7 +1169,14 @@ int ogs_nas_5gs_encode_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_emergen int ogs_nas_5gs_decode_eps_bearer_context_status(ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_bearer_context_status_t *source = (ogs_nas_eps_bearer_context_status_t *)pkbuf->data; + ogs_nas_eps_bearer_context_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_bearer_context_status_t *)pkbuf->data; eps_bearer_context_status->length = source->length; size = eps_bearer_context_status->length + sizeof(eps_bearer_context_status->length); @@ -1075,7 +1215,14 @@ int ogs_nas_5gs_encode_eps_bearer_context_status(ogs_pkbuf_t *pkbuf, ogs_nas_eps int ogs_nas_5gs_decode_eps_nas_message_container(ogs_nas_eps_nas_message_container_t *eps_nas_message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_nas_message_container_t *source = (ogs_nas_eps_nas_message_container_t *)pkbuf->data; + ogs_nas_eps_nas_message_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_nas_message_container_t *)pkbuf->data; eps_nas_message_container->length = be16toh(source->length); size = eps_nas_message_container->length + sizeof(eps_nas_message_container->length); @@ -1155,7 +1302,14 @@ int ogs_nas_5gs_encode_eps_nas_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_e int ogs_nas_5gs_decode_extended_emergency_number_list(ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_emergency_number_list_t *source = (ogs_nas_extended_emergency_number_list_t *)pkbuf->data; + ogs_nas_extended_emergency_number_list_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_emergency_number_list_t *)pkbuf->data; extended_emergency_number_list->length = be16toh(source->length); size = extended_emergency_number_list->length + sizeof(extended_emergency_number_list->length); @@ -1201,7 +1355,14 @@ int ogs_nas_5gs_encode_extended_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_5gs_decode_extended_drx_parameters(ogs_nas_extended_drx_parameters_t *extended_drx_parameters, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_drx_parameters_t *source = (ogs_nas_extended_drx_parameters_t *)pkbuf->data; + ogs_nas_extended_drx_parameters_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_drx_parameters_t *)pkbuf->data; extended_drx_parameters->length = source->length; size = extended_drx_parameters->length + sizeof(extended_drx_parameters->length); @@ -1272,7 +1433,14 @@ int ogs_nas_5gs_encode_imeisv_request(ogs_pkbuf_t *pkbuf, ogs_nas_imeisv_request int ogs_nas_5gs_decode_ladn_indication(ogs_nas_ladn_indication_t *ladn_indication, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ladn_indication_t *source = (ogs_nas_ladn_indication_t *)pkbuf->data; + ogs_nas_ladn_indication_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ladn_indication_t *)pkbuf->data; ladn_indication->length = be16toh(source->length); size = ladn_indication->length + sizeof(ladn_indication->length); @@ -1318,7 +1486,14 @@ int ogs_nas_5gs_encode_ladn_indication(ogs_pkbuf_t *pkbuf, ogs_nas_ladn_indicati int ogs_nas_5gs_decode_5gs_drx_parameters(ogs_nas_5gs_drx_parameters_t *drx_parameters, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_drx_parameters_t *source = (ogs_nas_5gs_drx_parameters_t *)pkbuf->data; + ogs_nas_5gs_drx_parameters_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_drx_parameters_t *)pkbuf->data; drx_parameters->length = source->length; size = drx_parameters->length + sizeof(drx_parameters->length); @@ -1391,7 +1566,14 @@ int ogs_nas_5gs_encode_5gs_identity_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_identit int ogs_nas_5gs_decode_ladn_information(ogs_nas_ladn_information_t *ladn_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ladn_information_t *source = (ogs_nas_ladn_information_t *)pkbuf->data; + ogs_nas_ladn_information_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ladn_information_t *)pkbuf->data; ladn_information->length = be16toh(source->length); size = ladn_information->length + sizeof(ladn_information->length); @@ -1501,7 +1683,14 @@ int ogs_nas_5gs_encode_ma_pdu_session_information(ogs_pkbuf_t *pkbuf, ogs_nas_ma int ogs_nas_5gs_decode_mapped_nssai(ogs_nas_mapped_nssai_t *mapped_nssai, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mapped_nssai_t *source = (ogs_nas_mapped_nssai_t *)pkbuf->data; + ogs_nas_mapped_nssai_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mapped_nssai_t *)pkbuf->data; mapped_nssai->length = source->length; size = mapped_nssai->length + sizeof(mapped_nssai->length); @@ -1540,7 +1729,14 @@ int ogs_nas_5gs_encode_mapped_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_mapped_nssai_t * int ogs_nas_5gs_decode_mobile_station_classmark_2(ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mobile_station_classmark_2_t *source = (ogs_nas_mobile_station_classmark_2_t *)pkbuf->data; + ogs_nas_mobile_station_classmark_2_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mobile_station_classmark_2_t *)pkbuf->data; mobile_station_classmark_2->length = source->length; size = mobile_station_classmark_2->length + sizeof(mobile_station_classmark_2->length); @@ -1611,7 +1807,14 @@ int ogs_nas_5gs_encode_key_set_identifier(ogs_pkbuf_t *pkbuf, ogs_nas_key_set_id int ogs_nas_5gs_decode_message_container(ogs_nas_message_container_t *message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_message_container_t *source = (ogs_nas_message_container_t *)pkbuf->data; + ogs_nas_message_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_message_container_t *)pkbuf->data; message_container->length = be16toh(source->length); size = message_container->length + sizeof(message_container->length); @@ -1691,7 +1894,14 @@ int ogs_nas_5gs_encode_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_security_ int ogs_nas_5gs_decode_network_name(ogs_nas_network_name_t *network_name, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_network_name_t *source = (ogs_nas_network_name_t *)pkbuf->data; + ogs_nas_network_name_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_network_name_t *)pkbuf->data; network_name->length = source->length; size = network_name->length + sizeof(network_name->length); @@ -1794,7 +2004,14 @@ int ogs_nas_5gs_encode_non_3gpp_nw_provided_policies(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_5gs_decode_nssai(ogs_nas_nssai_t *nssai, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nssai_t *source = (ogs_nas_nssai_t *)pkbuf->data; + ogs_nas_nssai_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nssai_t *)pkbuf->data; nssai->length = source->length; size = nssai->length + sizeof(nssai->length); @@ -1865,7 +2082,14 @@ int ogs_nas_5gs_encode_nssai_inclusion_mode(ogs_pkbuf_t *pkbuf, ogs_nas_nssai_in int ogs_nas_5gs_decode_operator_defined_access_category_definitions(ogs_nas_operator_defined_access_category_definitions_t *operator_defined_access_category_definitions, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_operator_defined_access_category_definitions_t *source = (ogs_nas_operator_defined_access_category_definitions_t *)pkbuf->data; + ogs_nas_operator_defined_access_category_definitions_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_operator_defined_access_category_definitions_t *)pkbuf->data; operator_defined_access_category_definitions->length = be16toh(source->length); size = operator_defined_access_category_definitions->length + sizeof(operator_defined_access_category_definitions->length); @@ -1911,7 +2135,14 @@ int ogs_nas_5gs_encode_operator_defined_access_category_definitions(ogs_pkbuf_t int ogs_nas_5gs_decode_payload_container(ogs_nas_payload_container_t *payload_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_payload_container_t *source = (ogs_nas_payload_container_t *)pkbuf->data; + ogs_nas_payload_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_payload_container_t *)pkbuf->data; payload_container->length = be16toh(source->length); size = payload_container->length + sizeof(payload_container->length); @@ -1957,7 +2188,14 @@ int ogs_nas_5gs_encode_payload_container(ogs_pkbuf_t *pkbuf, ogs_nas_payload_con int ogs_nas_5gs_decode_5gs_mobile_identity(ogs_nas_5gs_mobile_identity_t *mobile_identity, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_mobile_identity_t *source = (ogs_nas_5gs_mobile_identity_t *)pkbuf->data; + ogs_nas_5gs_mobile_identity_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_mobile_identity_t *)pkbuf->data; mobile_identity->length = be16toh(source->length); size = mobile_identity->length + sizeof(mobile_identity->length); @@ -2069,7 +2307,14 @@ int ogs_nas_5gs_encode_pdu_session_identity_2(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_se int ogs_nas_5gs_decode_pdu_session_reactivation_result(ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdu_session_reactivation_result_t *source = (ogs_nas_pdu_session_reactivation_result_t *)pkbuf->data; + ogs_nas_pdu_session_reactivation_result_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdu_session_reactivation_result_t *)pkbuf->data; pdu_session_reactivation_result->length = source->length; size = pdu_session_reactivation_result->length + sizeof(pdu_session_reactivation_result->length); @@ -2112,7 +2357,14 @@ int ogs_nas_5gs_encode_pdu_session_reactivation_result(ogs_pkbuf_t *pkbuf, ogs_n int ogs_nas_5gs_decode_pdu_session_reactivation_result_error_cause(ogs_nas_pdu_session_reactivation_result_error_cause_t *pdu_session_reactivation_result_error_cause, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdu_session_reactivation_result_error_cause_t *source = (ogs_nas_pdu_session_reactivation_result_error_cause_t *)pkbuf->data; + ogs_nas_pdu_session_reactivation_result_error_cause_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdu_session_reactivation_result_error_cause_t *)pkbuf->data; pdu_session_reactivation_result_error_cause->length = be16toh(source->length); size = pdu_session_reactivation_result_error_cause->length + sizeof(pdu_session_reactivation_result_error_cause->length); @@ -2158,7 +2410,14 @@ int ogs_nas_5gs_encode_pdu_session_reactivation_result_error_cause(ogs_pkbuf_t * int ogs_nas_5gs_decode_pdu_session_status(ogs_nas_pdu_session_status_t *pdu_session_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdu_session_status_t *source = (ogs_nas_pdu_session_status_t *)pkbuf->data; + ogs_nas_pdu_session_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdu_session_status_t *)pkbuf->data; pdu_session_status->length = source->length; size = pdu_session_status->length + sizeof(pdu_session_status->length); @@ -2201,7 +2460,14 @@ int ogs_nas_5gs_encode_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_sessio int ogs_nas_5gs_decode_plmn_list(ogs_nas_plmn_list_t *plmn_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_plmn_list_t *source = (ogs_nas_plmn_list_t *)pkbuf->data; + ogs_nas_plmn_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_plmn_list_t *)pkbuf->data; plmn_list->length = source->length; size = plmn_list->length + sizeof(plmn_list->length); @@ -2240,7 +2506,14 @@ int ogs_nas_5gs_encode_plmn_list(ogs_pkbuf_t *pkbuf, ogs_nas_plmn_list_t *plmn_l int ogs_nas_5gs_decode_rejected_nssai(ogs_nas_rejected_nssai_t *rejected_nssai, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_rejected_nssai_t *source = (ogs_nas_rejected_nssai_t *)pkbuf->data; + ogs_nas_rejected_nssai_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_rejected_nssai_t *)pkbuf->data; rejected_nssai->length = source->length; size = rejected_nssai->length + sizeof(rejected_nssai->length); @@ -2343,7 +2616,14 @@ int ogs_nas_5gs_encode_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_request_type_t * int ogs_nas_5gs_decode_s1_ue_network_capability(ogs_nas_s1_ue_network_capability_t *s1_ue_network_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_s1_ue_network_capability_t *source = (ogs_nas_s1_ue_network_capability_t *)pkbuf->data; + ogs_nas_s1_ue_network_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_s1_ue_network_capability_t *)pkbuf->data; s1_ue_network_capability->length = source->length; size = s1_ue_network_capability->length + sizeof(s1_ue_network_capability->length); @@ -2382,7 +2662,14 @@ int ogs_nas_5gs_encode_s1_ue_network_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_u int ogs_nas_5gs_decode_s1_ue_security_capability(ogs_nas_s1_ue_security_capability_t *s1_ue_security_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_s1_ue_security_capability_t *source = (ogs_nas_s1_ue_security_capability_t *)pkbuf->data; + ogs_nas_s1_ue_security_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_s1_ue_security_capability_t *)pkbuf->data; s1_ue_security_capability->length = source->length; size = s1_ue_security_capability->length + sizeof(s1_ue_security_capability->length); @@ -2421,7 +2708,14 @@ int ogs_nas_5gs_encode_s1_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_ int ogs_nas_5gs_decode_service_area_list(ogs_nas_service_area_list_t *service_area_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_service_area_list_t *source = (ogs_nas_service_area_list_t *)pkbuf->data; + ogs_nas_service_area_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_service_area_list_t *)pkbuf->data; service_area_list->length = source->length; size = service_area_list->length + sizeof(service_area_list->length); @@ -2460,7 +2754,14 @@ int ogs_nas_5gs_encode_service_area_list(ogs_pkbuf_t *pkbuf, ogs_nas_service_are int ogs_nas_5gs_decode_5gs_network_feature_support(ogs_nas_5gs_network_feature_support_t *network_feature_support, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_network_feature_support_t *source = (ogs_nas_5gs_network_feature_support_t *)pkbuf->data; + ogs_nas_5gs_network_feature_support_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_network_feature_support_t *)pkbuf->data; network_feature_support->length = source->length; size = network_feature_support->length + sizeof(network_feature_support->length); @@ -2531,7 +2832,14 @@ int ogs_nas_5gs_encode_sms_indication(ogs_pkbuf_t *pkbuf, ogs_nas_sms_indication int ogs_nas_5gs_decode_sor_transparent_container(ogs_nas_sor_transparent_container_t *sor_transparent_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_sor_transparent_container_t *source = (ogs_nas_sor_transparent_container_t *)pkbuf->data; + ogs_nas_sor_transparent_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_sor_transparent_container_t *)pkbuf->data; sor_transparent_container->length = be16toh(source->length); size = sor_transparent_container->length + sizeof(sor_transparent_container->length); @@ -2577,7 +2885,14 @@ int ogs_nas_5gs_encode_sor_transparent_container(ogs_pkbuf_t *pkbuf, ogs_nas_sor int ogs_nas_5gs_decode_supported_codec_list(ogs_nas_supported_codec_list_t *supported_codec_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_supported_codec_list_t *source = (ogs_nas_supported_codec_list_t *)pkbuf->data; + ogs_nas_supported_codec_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_supported_codec_list_t *)pkbuf->data; supported_codec_list->length = source->length; size = supported_codec_list->length + sizeof(supported_codec_list->length); @@ -2684,7 +2999,14 @@ int ogs_nas_5gs_encode_time_zone_and_time(ogs_pkbuf_t *pkbuf, ogs_nas_time_zone_ int ogs_nas_5gs_decode_ue_security_capability(ogs_nas_ue_security_capability_t *ue_security_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_security_capability_t *source = (ogs_nas_ue_security_capability_t *)pkbuf->data; + ogs_nas_ue_security_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_security_capability_t *)pkbuf->data; ue_security_capability->length = source->length; size = ue_security_capability->length + sizeof(ue_security_capability->length); @@ -2723,7 +3045,14 @@ int ogs_nas_5gs_encode_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_ue_sec int ogs_nas_5gs_decode_ue_usage_setting(ogs_nas_ue_usage_setting_t *ue_usage_setting, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_usage_setting_t *source = (ogs_nas_ue_usage_setting_t *)pkbuf->data; + ogs_nas_ue_usage_setting_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_usage_setting_t *)pkbuf->data; ue_usage_setting->length = source->length; size = ue_usage_setting->length + sizeof(ue_usage_setting->length); @@ -2762,7 +3091,14 @@ int ogs_nas_5gs_encode_ue_usage_setting(ogs_pkbuf_t *pkbuf, ogs_nas_ue_usage_set int ogs_nas_5gs_decode_ue_status(ogs_nas_ue_status_t *ue_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_status_t *source = (ogs_nas_ue_status_t *)pkbuf->data; + ogs_nas_ue_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_status_t *)pkbuf->data; ue_status->length = source->length; size = ue_status->length + sizeof(ue_status->length); @@ -2801,7 +3137,14 @@ int ogs_nas_5gs_encode_ue_status(ogs_pkbuf_t *pkbuf, ogs_nas_ue_status_t *ue_sta int ogs_nas_5gs_decode_uplink_data_status(ogs_nas_uplink_data_status_t *uplink_data_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_uplink_data_status_t *source = (ogs_nas_uplink_data_status_t *)pkbuf->data; + ogs_nas_uplink_data_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_uplink_data_status_t *)pkbuf->data; uplink_data_status->length = source->length; size = uplink_data_status->length + sizeof(uplink_data_status->length); @@ -2844,7 +3187,14 @@ int ogs_nas_5gs_encode_uplink_data_status(ogs_pkbuf_t *pkbuf, ogs_nas_uplink_dat int ogs_nas_5gs_decode_5gs_registration_result(ogs_nas_5gs_registration_result_t *registration_result, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_registration_result_t *source = (ogs_nas_5gs_registration_result_t *)pkbuf->data; + ogs_nas_5gs_registration_result_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_registration_result_t *)pkbuf->data; registration_result->length = source->length; size = registration_result->length + sizeof(registration_result->length); @@ -2883,7 +3233,14 @@ int ogs_nas_5gs_encode_5gs_registration_result(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_r int ogs_nas_5gs_decode_ue_radio_capability_id(ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_radio_capability_id_t *source = (ogs_nas_ue_radio_capability_id_t *)pkbuf->data; + ogs_nas_ue_radio_capability_id_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_radio_capability_id_t *)pkbuf->data; ue_radio_capability_id->length = source->length; size = ue_radio_capability_id->length + sizeof(ue_radio_capability_id->length); @@ -2988,7 +3345,14 @@ int ogs_nas_5gs_encode_5gs_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_reg int ogs_nas_5gs_decode_truncated_5g_s_tmsi_configuration(ogs_nas_truncated_5g_s_tmsi_configuration_t *truncated_s_tmsi_configuration, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_truncated_5g_s_tmsi_configuration_t *source = (ogs_nas_truncated_5g_s_tmsi_configuration_t *)pkbuf->data; + ogs_nas_truncated_5g_s_tmsi_configuration_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_truncated_5g_s_tmsi_configuration_t *)pkbuf->data; truncated_s_tmsi_configuration->length = source->length; size = truncated_s_tmsi_configuration->length + sizeof(truncated_s_tmsi_configuration->length); @@ -3027,7 +3391,14 @@ int ogs_nas_5gs_encode_truncated_5g_s_tmsi_configuration(ogs_pkbuf_t *pkbuf, ogs int ogs_nas_5gs_decode_wus_assistance_information(ogs_nas_wus_assistance_information_t *wus_assistance_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_wus_assistance_information_t *source = (ogs_nas_wus_assistance_information_t *)pkbuf->data; + ogs_nas_wus_assistance_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_wus_assistance_information_t *)pkbuf->data; wus_assistance_information->length = source->length; size = wus_assistance_information->length + sizeof(wus_assistance_information->length); @@ -3098,7 +3469,14 @@ int ogs_nas_5gs_encode_n5gc_indication(ogs_pkbuf_t *pkbuf, ogs_nas_n5gc_indicati int ogs_nas_5gs_decode_nb_n1_mode_drx_parameters(ogs_nas_nb_n1_mode_drx_parameters_t *nb_n1_mode_drx_parameters, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nb_n1_mode_drx_parameters_t *source = (ogs_nas_nb_n1_mode_drx_parameters_t *)pkbuf->data; + ogs_nas_nb_n1_mode_drx_parameters_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nb_n1_mode_drx_parameters_t *)pkbuf->data; nb_n1_mode_drx_parameters->length = source->length; size = nb_n1_mode_drx_parameters->length + sizeof(nb_n1_mode_drx_parameters->length); @@ -3169,7 +3547,14 @@ int ogs_nas_5gs_encode_additional_configuration_indication(ogs_pkbuf_t *pkbuf, o int ogs_nas_5gs_decode_extended_rejected_nssai(ogs_nas_extended_rejected_nssai_t *extended_rejected_nssai, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_rejected_nssai_t *source = (ogs_nas_extended_rejected_nssai_t *)pkbuf->data; + ogs_nas_extended_rejected_nssai_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_rejected_nssai_t *)pkbuf->data; extended_rejected_nssai->length = source->length; size = extended_rejected_nssai->length + sizeof(extended_rejected_nssai->length); @@ -3208,7 +3593,14 @@ int ogs_nas_5gs_encode_extended_rejected_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_exten int ogs_nas_5gs_decode_ue_request_type(ogs_nas_ue_request_type_t *ue_request_type, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_request_type_t *source = (ogs_nas_ue_request_type_t *)pkbuf->data; + ogs_nas_ue_request_type_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_request_type_t *)pkbuf->data; ue_request_type->length = source->length; size = ue_request_type->length + sizeof(ue_request_type->length); @@ -3247,7 +3639,14 @@ int ogs_nas_5gs_encode_ue_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_ue_request_ty int ogs_nas_5gs_decode_paging_restriction(ogs_nas_paging_restriction_t *paging_restriction, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_paging_restriction_t *source = (ogs_nas_paging_restriction_t *)pkbuf->data; + ogs_nas_paging_restriction_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_paging_restriction_t *)pkbuf->data; paging_restriction->length = source->length; size = paging_restriction->length + sizeof(paging_restriction->length); @@ -3286,7 +3685,14 @@ int ogs_nas_5gs_encode_paging_restriction(ogs_pkbuf_t *pkbuf, ogs_nas_paging_res int ogs_nas_5gs_decode_nid(ogs_nas_nid_t *nid, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nid_t *source = (ogs_nas_nid_t *)pkbuf->data; + ogs_nas_nid_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nid_t *)pkbuf->data; nid->length = source->length; size = nid->length + sizeof(nid->length); @@ -3363,7 +3769,14 @@ int ogs_nas_5gs_encode_5gs_tracking_area_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5g int ogs_nas_5gs_decode_peips_assistance_information(ogs_nas_peips_assistance_information_t *peips_assistance_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_peips_assistance_information_t *source = (ogs_nas_peips_assistance_information_t *)pkbuf->data; + ogs_nas_peips_assistance_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_peips_assistance_information_t *)pkbuf->data; peips_assistance_information->length = source->length; size = peips_assistance_information->length + sizeof(peips_assistance_information->length); @@ -3402,7 +3815,14 @@ int ogs_nas_5gs_encode_peips_assistance_information(ogs_pkbuf_t *pkbuf, ogs_nas_ int ogs_nas_5gs_decode_5gs_additional_request_result(ogs_nas_5gs_additional_request_result_t *additional_request_result, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_additional_request_result_t *source = (ogs_nas_5gs_additional_request_result_t *)pkbuf->data; + ogs_nas_5gs_additional_request_result_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_additional_request_result_t *)pkbuf->data; additional_request_result->length = source->length; size = additional_request_result->length + sizeof(additional_request_result->length); @@ -3441,7 +3861,14 @@ int ogs_nas_5gs_encode_5gs_additional_request_result(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_5gs_decode_nssrg_information(ogs_nas_nssrg_information_t *nssrg_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nssrg_information_t *source = (ogs_nas_nssrg_information_t *)pkbuf->data; + ogs_nas_nssrg_information_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nssrg_information_t *)pkbuf->data; nssrg_information->length = be16toh(source->length); size = nssrg_information->length + sizeof(nssrg_information->length); @@ -3487,7 +3914,14 @@ int ogs_nas_5gs_encode_nssrg_information(ogs_pkbuf_t *pkbuf, ogs_nas_nssrg_infor int ogs_nas_5gs_decode_list_of_plmns_to_be_used_in_disaster_condition(ogs_nas_list_of_plmns_to_be_used_in_disaster_condition_t *list_of_plmns_to_be_used_in_disaster_condition, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_list_of_plmns_to_be_used_in_disaster_condition_t *source = (ogs_nas_list_of_plmns_to_be_used_in_disaster_condition_t *)pkbuf->data; + ogs_nas_list_of_plmns_to_be_used_in_disaster_condition_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_list_of_plmns_to_be_used_in_disaster_condition_t *)pkbuf->data; list_of_plmns_to_be_used_in_disaster_condition->length = source->length; size = list_of_plmns_to_be_used_in_disaster_condition->length + sizeof(list_of_plmns_to_be_used_in_disaster_condition->length); @@ -3526,7 +3960,14 @@ int ogs_nas_5gs_encode_list_of_plmns_to_be_used_in_disaster_condition(ogs_pkbuf_ int ogs_nas_5gs_decode_registration_wait_range(ogs_nas_registration_wait_range_t *registration_wait_range, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_registration_wait_range_t *source = (ogs_nas_registration_wait_range_t *)pkbuf->data; + ogs_nas_registration_wait_range_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_registration_wait_range_t *)pkbuf->data; registration_wait_range->length = source->length; size = registration_wait_range->length + sizeof(registration_wait_range->length); @@ -3565,7 +4006,14 @@ int ogs_nas_5gs_encode_registration_wait_range(ogs_pkbuf_t *pkbuf, ogs_nas_regis int ogs_nas_5gs_decode_plmn_identity(ogs_nas_plmn_identity_t *plmn_identity, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_plmn_identity_t *source = (ogs_nas_plmn_identity_t *)pkbuf->data; + ogs_nas_plmn_identity_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_plmn_identity_t *)pkbuf->data; plmn_identity->length = source->length; size = plmn_identity->length + sizeof(plmn_identity->length); @@ -3604,7 +4052,14 @@ int ogs_nas_5gs_encode_plmn_identity(ogs_pkbuf_t *pkbuf, ogs_nas_plmn_identity_t int ogs_nas_5gs_decode_extended_cag_information_list(ogs_nas_extended_cag_information_list_t *extended_cag_information_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_cag_information_list_t *source = (ogs_nas_extended_cag_information_list_t *)pkbuf->data; + ogs_nas_extended_cag_information_list_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_cag_information_list_t *)pkbuf->data; extended_cag_information_list->length = be16toh(source->length); size = extended_cag_information_list->length + sizeof(extended_cag_information_list->length); @@ -3650,7 +4105,14 @@ int ogs_nas_5gs_encode_extended_cag_information_list(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_5gs_decode_nsag_information(ogs_nas_nsag_information_t *nsag_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nsag_information_t *source = (ogs_nas_nsag_information_t *)pkbuf->data; + ogs_nas_nsag_information_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nsag_information_t *)pkbuf->data; nsag_information->length = be16toh(source->length); size = nsag_information->length + sizeof(nsag_information->length); @@ -3696,7 +4158,14 @@ int ogs_nas_5gs_encode_nsag_information(ogs_pkbuf_t *pkbuf, ogs_nas_nsag_informa int ogs_nas_5gs_decode_5gs_tracking_area_identity_list(ogs_nas_5gs_tracking_area_identity_list_t *tracking_area_identity_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_tracking_area_identity_list_t *source = (ogs_nas_5gs_tracking_area_identity_list_t *)pkbuf->data; + ogs_nas_5gs_tracking_area_identity_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_tracking_area_identity_list_t *)pkbuf->data; tracking_area_identity_list->length = source->length; size = tracking_area_identity_list->length + sizeof(tracking_area_identity_list->length); @@ -3767,7 +4236,14 @@ int ogs_nas_5gs_encode_priority_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_priority_i int ogs_nas_5gs_decode_5gs_update_type(ogs_nas_5gs_update_type_t *update_type, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gs_update_type_t *source = (ogs_nas_5gs_update_type_t *)pkbuf->data; + ogs_nas_5gs_update_type_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gs_update_type_t *)pkbuf->data; update_type->length = source->length; size = update_type->length + sizeof(update_type->length); @@ -3806,7 +4282,14 @@ int ogs_nas_5gs_encode_5gs_update_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_update_ty int ogs_nas_5gs_decode_5gsm_capability(ogs_nas_5gsm_capability_t *gsm_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gsm_capability_t *source = (ogs_nas_5gsm_capability_t *)pkbuf->data; + ogs_nas_5gsm_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gsm_capability_t *)pkbuf->data; gsm_capability->length = source->length; size = gsm_capability->length + sizeof(gsm_capability->length); @@ -3845,7 +4328,14 @@ int ogs_nas_5gs_encode_5gsm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_capabili int ogs_nas_5gs_decode_pdu_address(ogs_nas_pdu_address_t *pdu_address, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdu_address_t *source = (ogs_nas_pdu_address_t *)pkbuf->data; + ogs_nas_pdu_address_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdu_address_t *)pkbuf->data; pdu_address->length = source->length; size = pdu_address->length + sizeof(pdu_address->length); @@ -3916,7 +4406,14 @@ int ogs_nas_5gs_encode_pdu_session_type(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_ int ogs_nas_5gs_decode_qos_flow_descriptions(ogs_nas_qos_flow_descriptions_t *qos_flow_descriptions, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_qos_flow_descriptions_t *source = (ogs_nas_qos_flow_descriptions_t *)pkbuf->data; + ogs_nas_qos_flow_descriptions_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_qos_flow_descriptions_t *)pkbuf->data; qos_flow_descriptions->length = be16toh(source->length); size = qos_flow_descriptions->length + sizeof(qos_flow_descriptions->length); @@ -3962,7 +4459,14 @@ int ogs_nas_5gs_encode_qos_flow_descriptions(ogs_pkbuf_t *pkbuf, ogs_nas_qos_flo int ogs_nas_5gs_decode_qos_rules(ogs_nas_qos_rules_t *qos_rules, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_qos_rules_t *source = (ogs_nas_qos_rules_t *)pkbuf->data; + ogs_nas_qos_rules_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_qos_rules_t *)pkbuf->data; qos_rules->length = be16toh(source->length); size = qos_rules->length + sizeof(qos_rules->length); @@ -4008,7 +4512,14 @@ int ogs_nas_5gs_encode_qos_rules(ogs_pkbuf_t *pkbuf, ogs_nas_qos_rules_t *qos_ru int ogs_nas_5gs_decode_session_ambr(ogs_nas_session_ambr_t *session_ambr, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_session_ambr_t *source = (ogs_nas_session_ambr_t *)pkbuf->data; + ogs_nas_session_ambr_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_session_ambr_t *)pkbuf->data; session_ambr->length = source->length; size = session_ambr->length + sizeof(session_ambr->length); @@ -4053,7 +4564,14 @@ int ogs_nas_5gs_encode_session_ambr(ogs_pkbuf_t *pkbuf, ogs_nas_session_ambr_t * int ogs_nas_5gs_decode_sm_pdu_dn_request_container(ogs_nas_sm_pdu_dn_request_container_t *sm_pdu_dn_request_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_sm_pdu_dn_request_container_t *source = (ogs_nas_sm_pdu_dn_request_container_t *)pkbuf->data; + ogs_nas_sm_pdu_dn_request_container_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_sm_pdu_dn_request_container_t *)pkbuf->data; sm_pdu_dn_request_container->length = source->length; size = sm_pdu_dn_request_container->length + sizeof(sm_pdu_dn_request_container->length); @@ -4124,7 +4642,14 @@ int ogs_nas_5gs_encode_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_ssc_mode_t *ssc_mode int ogs_nas_5gs_decode_re_attempt_indicator(ogs_nas_re_attempt_indicator_t *re_attempt_indicator, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_re_attempt_indicator_t *source = (ogs_nas_re_attempt_indicator_t *)pkbuf->data; + ogs_nas_re_attempt_indicator_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_re_attempt_indicator_t *)pkbuf->data; re_attempt_indicator->length = source->length; size = re_attempt_indicator->length + sizeof(re_attempt_indicator->length); @@ -4163,7 +4688,14 @@ int ogs_nas_5gs_encode_re_attempt_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_re_attem int ogs_nas_5gs_decode_5gsm_network_feature_support(ogs_nas_5gsm_network_feature_support_t *gsm_network_feature_support, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gsm_network_feature_support_t *source = (ogs_nas_5gsm_network_feature_support_t *)pkbuf->data; + ogs_nas_5gsm_network_feature_support_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gsm_network_feature_support_t *)pkbuf->data; gsm_network_feature_support->length = source->length; size = gsm_network_feature_support->length + sizeof(gsm_network_feature_support->length); @@ -4236,7 +4768,14 @@ int ogs_nas_5gs_encode_5gsm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_cause_t *gsm_ int ogs_nas_5gs_decode_serving_plmn_rate_control(ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_serving_plmn_rate_control_t *source = (ogs_nas_serving_plmn_rate_control_t *)pkbuf->data; + ogs_nas_serving_plmn_rate_control_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_serving_plmn_rate_control_t *)pkbuf->data; serving_plmn_rate_control->length = source->length; size = serving_plmn_rate_control->length + sizeof(serving_plmn_rate_control->length); @@ -4275,7 +4814,14 @@ int ogs_nas_5gs_encode_serving_plmn_rate_control(ogs_pkbuf_t *pkbuf, ogs_nas_ser int ogs_nas_5gs_decode_5gsm_congestion_re_attempt_indicator(ogs_nas_5gsm_congestion_re_attempt_indicator_t *gsm_congestion_re_attempt_indicator, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_5gsm_congestion_re_attempt_indicator_t *source = (ogs_nas_5gsm_congestion_re_attempt_indicator_t *)pkbuf->data; + ogs_nas_5gsm_congestion_re_attempt_indicator_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_5gsm_congestion_re_attempt_indicator_t *)pkbuf->data; gsm_congestion_re_attempt_indicator->length = source->length; size = gsm_congestion_re_attempt_indicator->length + sizeof(gsm_congestion_re_attempt_indicator->length); @@ -4314,7 +4860,14 @@ int ogs_nas_5gs_encode_5gsm_congestion_re_attempt_indicator(ogs_pkbuf_t *pkbuf, int ogs_nas_5gs_decode_atsss_container(ogs_nas_atsss_container_t *atsss_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_atsss_container_t *source = (ogs_nas_atsss_container_t *)pkbuf->data; + ogs_nas_atsss_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_atsss_container_t *)pkbuf->data; atsss_container->length = be16toh(source->length); size = atsss_container->length + sizeof(atsss_container->length); @@ -4392,7 +4945,14 @@ int ogs_nas_5gs_encode_control_plane_only_indication(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_5gs_decode_ip_header_compression_configuration(ogs_nas_ip_header_compression_configuration_t *ip_header_compression_configuration, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ip_header_compression_configuration_t *source = (ogs_nas_ip_header_compression_configuration_t *)pkbuf->data; + ogs_nas_ip_header_compression_configuration_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ip_header_compression_configuration_t *)pkbuf->data; ip_header_compression_configuration->length = source->length; size = ip_header_compression_configuration->length + sizeof(ip_header_compression_configuration->length); @@ -4431,7 +4991,14 @@ int ogs_nas_5gs_encode_ip_header_compression_configuration(ogs_pkbuf_t *pkbuf, o int ogs_nas_5gs_decode_header_compression_configuration(ogs_nas_header_compression_configuration_t *header_compression_configuration, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_header_compression_configuration_t *source = (ogs_nas_header_compression_configuration_t *)pkbuf->data; + ogs_nas_header_compression_configuration_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_header_compression_configuration_t *)pkbuf->data; header_compression_configuration->length = source->length; size = header_compression_configuration->length + sizeof(header_compression_configuration->length); @@ -4474,7 +5041,14 @@ int ogs_nas_5gs_encode_header_compression_configuration(ogs_pkbuf_t *pkbuf, ogs_ int ogs_nas_5gs_decode_ds_tt_ethernet_port_mac_address(ogs_nas_ds_tt_ethernet_port_mac_address_t *ds_tt_ethernet_port_mac_address, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ds_tt_ethernet_port_mac_address_t *source = (ogs_nas_ds_tt_ethernet_port_mac_address_t *)pkbuf->data; + ogs_nas_ds_tt_ethernet_port_mac_address_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ds_tt_ethernet_port_mac_address_t *)pkbuf->data; ds_tt_ethernet_port_mac_address->length = source->length; size = ds_tt_ethernet_port_mac_address->length + sizeof(ds_tt_ethernet_port_mac_address->length); @@ -4513,7 +5087,14 @@ int ogs_nas_5gs_encode_ds_tt_ethernet_port_mac_address(ogs_pkbuf_t *pkbuf, ogs_n int ogs_nas_5gs_decode_ue_ds_tt_residence_time(ogs_nas_ue_ds_tt_residence_time_t *ue_ds_tt_residence_time, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_ds_tt_residence_time_t *source = (ogs_nas_ue_ds_tt_residence_time_t *)pkbuf->data; + ogs_nas_ue_ds_tt_residence_time_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_ds_tt_residence_time_t *)pkbuf->data; ue_ds_tt_residence_time->length = source->length; size = ue_ds_tt_residence_time->length + sizeof(ue_ds_tt_residence_time->length); @@ -4552,7 +5133,14 @@ int ogs_nas_5gs_encode_ue_ds_tt_residence_time(ogs_pkbuf_t *pkbuf, ogs_nas_ue_ds int ogs_nas_5gs_decode_port_management_information_container(ogs_nas_port_management_information_container_t *port_management_information_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_port_management_information_container_t *source = (ogs_nas_port_management_information_container_t *)pkbuf->data; + ogs_nas_port_management_information_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_port_management_information_container_t *)pkbuf->data; port_management_information_container->length = be16toh(source->length); size = port_management_information_container->length + sizeof(port_management_information_container->length); @@ -4598,7 +5186,14 @@ int ogs_nas_5gs_encode_port_management_information_container(ogs_pkbuf_t *pkbuf, int ogs_nas_5gs_decode_ethernet_header_compression_configuration(ogs_nas_ethernet_header_compression_configuration_t *ethernet_header_compression_configuration, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ethernet_header_compression_configuration_t *source = (ogs_nas_ethernet_header_compression_configuration_t *)pkbuf->data; + ogs_nas_ethernet_header_compression_configuration_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ethernet_header_compression_configuration_t *)pkbuf->data; ethernet_header_compression_configuration->length = source->length; size = ethernet_header_compression_configuration->length + sizeof(ethernet_header_compression_configuration->length); @@ -4669,7 +5264,14 @@ int ogs_nas_5gs_encode_always_on_pdu_session_indication(ogs_pkbuf_t *pkbuf, ogs_ int ogs_nas_5gs_decode_requested_mbs_container(ogs_nas_requested_mbs_container_t *requested_mbs_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_requested_mbs_container_t *source = (ogs_nas_requested_mbs_container_t *)pkbuf->data; + ogs_nas_requested_mbs_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_requested_mbs_container_t *)pkbuf->data; requested_mbs_container->length = be16toh(source->length); size = requested_mbs_container->length + sizeof(requested_mbs_container->length); @@ -4715,7 +5317,14 @@ int ogs_nas_5gs_encode_requested_mbs_container(ogs_pkbuf_t *pkbuf, ogs_nas_reque int ogs_nas_5gs_decode_received_mbs_container(ogs_nas_received_mbs_container_t *received_mbs_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_received_mbs_container_t *source = (ogs_nas_received_mbs_container_t *)pkbuf->data; + ogs_nas_received_mbs_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_received_mbs_container_t *)pkbuf->data; received_mbs_container->length = be16toh(source->length); size = received_mbs_container->length + sizeof(received_mbs_container->length); @@ -4761,7 +5370,14 @@ int ogs_nas_5gs_encode_received_mbs_container(ogs_pkbuf_t *pkbuf, ogs_nas_receiv int ogs_nas_5gs_decode_pdu_session_pair_id(ogs_nas_pdu_session_pair_id_t *pdu_session_pair_id, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdu_session_pair_id_t *source = (ogs_nas_pdu_session_pair_id_t *)pkbuf->data; + ogs_nas_pdu_session_pair_id_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdu_session_pair_id_t *)pkbuf->data; pdu_session_pair_id->length = source->length; size = pdu_session_pair_id->length + sizeof(pdu_session_pair_id->length); @@ -4800,7 +5416,14 @@ int ogs_nas_5gs_encode_pdu_session_pair_id(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_sessi int ogs_nas_5gs_decode_rsn(ogs_nas_rsn_t *rsn, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_rsn_t *source = (ogs_nas_rsn_t *)pkbuf->data; + ogs_nas_rsn_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_rsn_t *)pkbuf->data; rsn->length = source->length; size = rsn->length + sizeof(rsn->length); @@ -4903,7 +5526,14 @@ int ogs_nas_5gs_encode_allowed_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_allowed_ssc_ int ogs_nas_5gs_decode_extended_protocol_configuration_options(ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_protocol_configuration_options_t *source = (ogs_nas_extended_protocol_configuration_options_t *)pkbuf->data; + ogs_nas_extended_protocol_configuration_options_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_protocol_configuration_options_t *)pkbuf->data; extended_protocol_configuration_options->length = be16toh(source->length); size = extended_protocol_configuration_options->length + sizeof(extended_protocol_configuration_options->length); @@ -4983,7 +5613,14 @@ int ogs_nas_5gs_encode_integrity_protection_maximum_data_rate(ogs_pkbuf_t *pkbuf int ogs_nas_5gs_decode_mapped_eps_bearer_contexts(ogs_nas_mapped_eps_bearer_contexts_t *mapped_eps_bearer_contexts, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mapped_eps_bearer_contexts_t *source = (ogs_nas_mapped_eps_bearer_contexts_t *)pkbuf->data; + ogs_nas_mapped_eps_bearer_contexts_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mapped_eps_bearer_contexts_t *)pkbuf->data; mapped_eps_bearer_contexts->length = be16toh(source->length); size = mapped_eps_bearer_contexts->length + sizeof(mapped_eps_bearer_contexts->length); diff --git a/lib/nas/5gs/support/nas-message.py b/lib/nas/5gs/support/nas-message.py index 24d1053fd..42e33cd26 100644 --- a/lib/nas/5gs/support/nas-message.py +++ b/lib/nas/5gs/support/nas-message.py @@ -447,7 +447,12 @@ for (k, v) in sorted_type_list: f.write("int ogs_nas_5gs_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf)\n" % (v_lower(k), v_lower(k), get_value(k))) f.write("{\n") f.write(" int size = 0;\n") - f.write(" ogs_nas_%s_t *source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % (v_lower(k), v_lower(k))) + f.write(" ogs_nas_%s_t *source = NULL;\n\n" % v_lower(k)) + f.write(" if (pkbuf->len < 2) {\n") + f.write(" ogs_error(\"Not enough pkbuf [len:%d]\", pkbuf->len);\n") + f.write(" return -1;\n") + f.write(" }\n\n") + f.write(" source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % v_lower(k)) f.write(" %s->length = be16toh(source->length);\n" % get_value(k)) f.write(" size = %s->length + sizeof(%s->length);\n\n" % (get_value(k), get_value(k))) f.write(" if (ogs_pkbuf_pull(pkbuf, size) == NULL) {\n") @@ -480,7 +485,12 @@ for (k, v) in sorted_type_list: f.write("int ogs_nas_5gs_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf)\n" % (v_lower(k), v_lower(k), get_value(k))) f.write("{\n") f.write(" int size = 0;\n") - f.write(" ogs_nas_%s_t *source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % (v_lower(k), v_lower(k))) + f.write(" ogs_nas_%s_t *source = NULL;\n\n" % v_lower(k)) + f.write(" if (pkbuf->len < 1) {\n") + f.write(" ogs_error(\"Not enough pkbuf [len:%d]\", pkbuf->len);\n") + f.write(" return -1;\n") + f.write(" }\n\n") + f.write(" source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % v_lower(k)) f.write(" %s->length = source->length;\n" % get_value(k)) f.write(" size = %s->length + sizeof(%s->length);\n\n" % (get_value(k), get_value(k))) f.write(" if (ogs_pkbuf_pull(pkbuf, size) == NULL) {\n") diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index f8a049deb..5e65c0942 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -128,8 +128,7 @@ void ogs_nas_build_s_nssai( pos = 0; - if (nas_s_nssai_ie->sst) - nas_s_nssai->buffer[pos++] = nas_s_nssai_ie->sst; + nas_s_nssai->buffer[pos++] = nas_s_nssai_ie->sst; if (nas_s_nssai_ie->sd.v != OGS_S_NSSAI_NO_SD_VALUE || @@ -141,7 +140,7 @@ void ogs_nas_build_s_nssai( * "no SD value associated with the SST". */ (nas_s_nssai_ie->sd.v == OGS_S_NSSAI_NO_SD_VALUE && - nas_s_nssai_ie->mapped_hplmn_sst && + nas_s_nssai_ie->mapped_hplmn_sst_presence && nas_s_nssai_ie->mapped_hplmn_sd.v != OGS_S_NSSAI_NO_SD_VALUE)) { v = ogs_htobe24(nas_s_nssai_ie->sd); @@ -149,7 +148,7 @@ void ogs_nas_build_s_nssai( pos += 3; } - if (nas_s_nssai_ie->mapped_hplmn_sst) + if (nas_s_nssai_ie->mapped_hplmn_sst_presence) nas_s_nssai->buffer[pos++] = nas_s_nssai_ie->mapped_hplmn_sst; if (nas_s_nssai_ie->mapped_hplmn_sd.v != OGS_S_NSSAI_NO_SD_VALUE) { @@ -169,14 +168,19 @@ void ogs_nas_build_s_nssai2( ogs_assert(nas_s_nssai); ogs_assert(s_nssai); - ogs_assert(mapped_hplmn); memset(&ie, 0, sizeof(ie)); ie.sst = s_nssai->sst; ie.sd.v = s_nssai->sd.v; - ie.mapped_hplmn_sst = mapped_hplmn->sst; - ie.mapped_hplmn_sd.v = mapped_hplmn->sd.v; + + if (mapped_hplmn) { + ie.mapped_hplmn_sst_presence = true; + ie.mapped_hplmn_sst = mapped_hplmn->sst; + ie.mapped_hplmn_sd.v = mapped_hplmn->sd.v; + } else { + ie.mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; + } ogs_nas_build_s_nssai(nas_s_nssai, &ie); } @@ -240,8 +244,10 @@ int ogs_nas_parse_s_nssai( pos += 3; } - if (mapped_hplmn_sst) + if (mapped_hplmn_sst) { nas_s_nssai_ie->mapped_hplmn_sst = nas_s_nssai->buffer[pos++]; + nas_s_nssai_ie->mapped_hplmn_sst_presence = true; + } if (mapped_hplmn_sd) { memcpy(&v, nas_s_nssai->buffer+pos, 3); diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h index b7ff296ad..b20e7b588 100644 --- a/lib/nas/5gs/types.h +++ b/lib/nas/5gs/types.h @@ -66,6 +66,7 @@ typedef struct ogs_nas_s_nssai_ie_s { uint8_t sst; ogs_uint24_t sd; uint8_t mapped_hplmn_sst; + bool mapped_hplmn_sst_presence; ogs_uint24_t mapped_hplmn_sd; } __attribute__ ((packed)) ogs_nas_s_nssai_ie_t; @@ -1052,7 +1053,7 @@ typedef struct ogs_nas_qos_rule_s { struct { ED3(uint8_t spare:1;, uint8_t segregation:1;, - uint8_t identifier:4;) + uint8_t identifier:6;) }; uint8_t flags; } flow; diff --git a/lib/nas/eps/ies.c b/lib/nas/eps/ies.c index 8144341b8..8a221d761 100644 --- a/lib/nas/eps/ies.c +++ b/lib/nas/eps/ies.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2024-01-21 18:50:03.402793 by acetcom + * Created on: 2024-12-11 21:08:02.462921 by acetcom * from 24301-h90.docx ******************************************************************************/ @@ -48,7 +48,14 @@ int ogs_nas_eps_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) int ogs_nas_eps_decode_additional_information(ogs_nas_additional_information_t *additional_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_additional_information_t *source = (ogs_nas_additional_information_t *)pkbuf->data; + ogs_nas_additional_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_additional_information_t *)pkbuf->data; additional_information->length = source->length; size = additional_information->length + sizeof(additional_information->length); @@ -119,7 +126,14 @@ int ogs_nas_eps_encode_device_properties(ogs_pkbuf_t *pkbuf, ogs_nas_device_prop int ogs_nas_eps_decode_eps_bearer_context_status(ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_bearer_context_status_t *source = (ogs_nas_eps_bearer_context_status_t *)pkbuf->data; + ogs_nas_eps_bearer_context_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_bearer_context_status_t *)pkbuf->data; eps_bearer_context_status->length = source->length; size = eps_bearer_context_status->length + sizeof(eps_bearer_context_status->length); @@ -158,7 +172,14 @@ int ogs_nas_eps_encode_eps_bearer_context_status(ogs_pkbuf_t *pkbuf, ogs_nas_eps int ogs_nas_eps_decode_supported_codec_list(ogs_nas_supported_codec_list_t *supported_codec_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_supported_codec_list_t *source = (ogs_nas_supported_codec_list_t *)pkbuf->data; + ogs_nas_supported_codec_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_supported_codec_list_t *)pkbuf->data; supported_codec_list->length = source->length; size = supported_codec_list->length + sizeof(supported_codec_list->length); @@ -235,7 +256,14 @@ int ogs_nas_eps_encode_location_area_identification(ogs_pkbuf_t *pkbuf, ogs_nas_ int ogs_nas_eps_decode_mobile_identity(ogs_nas_mobile_identity_t *mobile_identity, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mobile_identity_t *source = (ogs_nas_mobile_identity_t *)pkbuf->data; + ogs_nas_mobile_identity_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mobile_identity_t *)pkbuf->data; mobile_identity->length = source->length; size = mobile_identity->length + sizeof(mobile_identity->length); @@ -283,7 +311,14 @@ int ogs_nas_eps_encode_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_mobile_identi int ogs_nas_eps_decode_mobile_station_classmark_2(ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mobile_station_classmark_2_t *source = (ogs_nas_mobile_station_classmark_2_t *)pkbuf->data; + ogs_nas_mobile_station_classmark_2_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mobile_station_classmark_2_t *)pkbuf->data; mobile_station_classmark_2->length = source->length; size = mobile_station_classmark_2->length + sizeof(mobile_station_classmark_2->length); @@ -322,7 +357,14 @@ int ogs_nas_eps_encode_mobile_station_classmark_2(ogs_pkbuf_t *pkbuf, ogs_nas_mo int ogs_nas_eps_decode_mobile_station_classmark_3(ogs_nas_mobile_station_classmark_3_t *mobile_station_classmark_3, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_mobile_station_classmark_3_t *source = (ogs_nas_mobile_station_classmark_3_t *)pkbuf->data; + ogs_nas_mobile_station_classmark_3_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_mobile_station_classmark_3_t *)pkbuf->data; mobile_station_classmark_3->length = source->length; size = mobile_station_classmark_3->length + sizeof(mobile_station_classmark_3->length); @@ -361,7 +403,14 @@ int ogs_nas_eps_encode_mobile_station_classmark_3(ogs_pkbuf_t *pkbuf, ogs_nas_mo int ogs_nas_eps_decode_plmn_list(ogs_nas_plmn_list_t *plmn_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_plmn_list_t *source = (ogs_nas_plmn_list_t *)pkbuf->data; + ogs_nas_plmn_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_plmn_list_t *)pkbuf->data; plmn_list->length = source->length; size = plmn_list->length + sizeof(plmn_list->length); @@ -464,7 +513,14 @@ int ogs_nas_eps_encode_additional_update_type(ogs_pkbuf_t *pkbuf, ogs_nas_additi int ogs_nas_eps_decode_authentication_failure_parameter(ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_failure_parameter_t *source = (ogs_nas_authentication_failure_parameter_t *)pkbuf->data; + ogs_nas_authentication_failure_parameter_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_failure_parameter_t *)pkbuf->data; authentication_failure_parameter->length = source->length; size = authentication_failure_parameter->length + sizeof(authentication_failure_parameter->length); @@ -571,7 +627,14 @@ int ogs_nas_eps_encode_eps_attach_type(ogs_pkbuf_t *pkbuf, ogs_nas_eps_attach_ty int ogs_nas_eps_decode_eps_mobile_identity(ogs_nas_eps_mobile_identity_t *eps_mobile_identity, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_mobile_identity_t *source = (ogs_nas_eps_mobile_identity_t *)pkbuf->data; + ogs_nas_eps_mobile_identity_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_mobile_identity_t *)pkbuf->data; eps_mobile_identity->length = source->length; size = eps_mobile_identity->length + sizeof(eps_mobile_identity->length); @@ -621,7 +684,14 @@ int ogs_nas_eps_encode_eps_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_eps_mobil int ogs_nas_eps_decode_eps_network_feature_support(ogs_nas_eps_network_feature_support_t *eps_network_feature_support, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_network_feature_support_t *source = (ogs_nas_eps_network_feature_support_t *)pkbuf->data; + ogs_nas_eps_network_feature_support_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_network_feature_support_t *)pkbuf->data; eps_network_feature_support->length = source->length; size = eps_network_feature_support->length + sizeof(eps_network_feature_support->length); @@ -728,7 +798,14 @@ int ogs_nas_eps_encode_eps_update_type(ogs_pkbuf_t *pkbuf, ogs_nas_eps_update_ty int ogs_nas_eps_decode_esm_message_container(ogs_nas_esm_message_container_t *esm_message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_esm_message_container_t *source = (ogs_nas_esm_message_container_t *)pkbuf->data; + ogs_nas_esm_message_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_esm_message_container_t *)pkbuf->data; esm_message_container->length = be16toh(source->length); size = esm_message_container->length + sizeof(esm_message_container->length); @@ -808,7 +885,14 @@ int ogs_nas_eps_encode_gprs_timer(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_t *gprs int ogs_nas_eps_decode_gprs_timer_2(ogs_nas_gprs_timer_2_t *gprs_timer_2, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_gprs_timer_2_t *source = (ogs_nas_gprs_timer_2_t *)pkbuf->data; + ogs_nas_gprs_timer_2_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_gprs_timer_2_t *)pkbuf->data; gprs_timer_2->length = source->length; size = gprs_timer_2->length + sizeof(gprs_timer_2->length); @@ -847,7 +931,14 @@ int ogs_nas_eps_encode_gprs_timer_2(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_2_t * int ogs_nas_eps_decode_gprs_timer_3(ogs_nas_gprs_timer_3_t *gprs_timer_3, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_gprs_timer_3_t *source = (ogs_nas_gprs_timer_3_t *)pkbuf->data; + ogs_nas_gprs_timer_3_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_gprs_timer_3_t *)pkbuf->data; gprs_timer_3->length = source->length; size = gprs_timer_3->length + sizeof(gprs_timer_3->length); @@ -986,7 +1077,14 @@ int ogs_nas_eps_encode_ksi_and_sequence_number(ogs_pkbuf_t *pkbuf, ogs_nas_ksi_a int ogs_nas_eps_decode_authentication_parameter_autn(ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_parameter_autn_t *source = (ogs_nas_authentication_parameter_autn_t *)pkbuf->data; + ogs_nas_authentication_parameter_autn_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_parameter_autn_t *)pkbuf->data; authentication_parameter_autn->length = source->length; size = authentication_parameter_autn->length + sizeof(authentication_parameter_autn->length); @@ -1025,7 +1123,14 @@ int ogs_nas_eps_encode_authentication_parameter_autn(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_eps_decode_ms_network_capability(ogs_nas_ms_network_capability_t *ms_network_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ms_network_capability_t *source = (ogs_nas_ms_network_capability_t *)pkbuf->data; + ogs_nas_ms_network_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ms_network_capability_t *)pkbuf->data; ms_network_capability->length = source->length; size = ms_network_capability->length + sizeof(ms_network_capability->length); @@ -1128,7 +1233,14 @@ int ogs_nas_eps_encode_key_set_identifier(ogs_pkbuf_t *pkbuf, ogs_nas_key_set_id int ogs_nas_eps_decode_eps_message_container(ogs_nas_eps_message_container_t *eps_message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_message_container_t *source = (ogs_nas_eps_message_container_t *)pkbuf->data; + ogs_nas_eps_message_container_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_message_container_t *)pkbuf->data; eps_message_container->length = source->length; size = eps_message_container->length + sizeof(eps_message_container->length); @@ -1201,7 +1313,14 @@ int ogs_nas_eps_encode_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_security_ int ogs_nas_eps_decode_network_name(ogs_nas_network_name_t *network_name, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_network_name_t *source = (ogs_nas_network_name_t *)pkbuf->data; + ogs_nas_network_name_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_network_name_t *)pkbuf->data; network_name->length = source->length; size = network_name->length + sizeof(network_name->length); @@ -1240,7 +1359,14 @@ int ogs_nas_eps_encode_network_name(ogs_pkbuf_t *pkbuf, ogs_nas_network_name_t * int ogs_nas_eps_decode_network_resource_identifier_container(ogs_nas_network_resource_identifier_container_t *network_resource_identifier_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_network_resource_identifier_container_t *source = (ogs_nas_network_resource_identifier_container_t *)pkbuf->data; + ogs_nas_network_resource_identifier_container_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_network_resource_identifier_container_t *)pkbuf->data; network_resource_identifier_container->length = source->length; size = network_resource_identifier_container->length + sizeof(network_resource_identifier_container->length); @@ -1665,7 +1791,14 @@ int ogs_nas_eps_encode_tracking_area_identity(ogs_pkbuf_t *pkbuf, ogs_nas_tracki int ogs_nas_eps_decode_tracking_area_identity_list(ogs_nas_tracking_area_identity_list_t *tracking_area_identity_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_tracking_area_identity_list_t *source = (ogs_nas_tracking_area_identity_list_t *)pkbuf->data; + ogs_nas_tracking_area_identity_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_tracking_area_identity_list_t *)pkbuf->data; tracking_area_identity_list->length = source->length; size = tracking_area_identity_list->length + sizeof(tracking_area_identity_list->length); @@ -1704,7 +1837,14 @@ int ogs_nas_eps_encode_tracking_area_identity_list(ogs_pkbuf_t *pkbuf, ogs_nas_t int ogs_nas_eps_decode_ue_network_capability(ogs_nas_ue_network_capability_t *ue_network_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_network_capability_t *source = (ogs_nas_ue_network_capability_t *)pkbuf->data; + ogs_nas_ue_network_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_network_capability_t *)pkbuf->data; ue_network_capability->length = source->length; size = ue_network_capability->length + sizeof(ue_network_capability->length); @@ -1775,7 +1915,14 @@ int ogs_nas_eps_encode_ue_radio_capability_information_update_needed(ogs_pkbuf_t int ogs_nas_eps_decode_ue_security_capability(ogs_nas_ue_security_capability_t *ue_security_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_security_capability_t *source = (ogs_nas_ue_security_capability_t *)pkbuf->data; + ogs_nas_ue_security_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_security_capability_t *)pkbuf->data; ue_security_capability->length = source->length; size = ue_security_capability->length + sizeof(ue_security_capability->length); @@ -1814,7 +1961,14 @@ int ogs_nas_eps_encode_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_ue_sec int ogs_nas_eps_decode_emergency_number_list(ogs_nas_emergency_number_list_t *emergency_number_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_emergency_number_list_t *source = (ogs_nas_emergency_number_list_t *)pkbuf->data; + ogs_nas_emergency_number_list_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_emergency_number_list_t *)pkbuf->data; emergency_number_list->length = source->length; size = emergency_number_list->length + sizeof(emergency_number_list->length); @@ -1853,7 +2007,14 @@ int ogs_nas_eps_encode_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_emergen int ogs_nas_eps_decode_extended_emergency_number_list(ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_emergency_number_list_t *source = (ogs_nas_extended_emergency_number_list_t *)pkbuf->data; + ogs_nas_extended_emergency_number_list_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_emergency_number_list_t *)pkbuf->data; extended_emergency_number_list->length = be16toh(source->length); size = extended_emergency_number_list->length + sizeof(extended_emergency_number_list->length); @@ -1899,7 +2060,14 @@ int ogs_nas_eps_encode_extended_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_eps_decode_cli(ogs_nas_cli_t *cli, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_cli_t *source = (ogs_nas_cli_t *)pkbuf->data; + ogs_nas_cli_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_cli_t *)pkbuf->data; cli->length = source->length; size = cli->length + sizeof(cli->length); @@ -1972,7 +2140,14 @@ int ogs_nas_eps_encode_ss_code(ogs_pkbuf_t *pkbuf, ogs_nas_ss_code_t *ss_code) int ogs_nas_eps_decode_authentication_response_parameter(ogs_nas_authentication_response_parameter_t *authentication_response_parameter, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_authentication_response_parameter_t *source = (ogs_nas_authentication_response_parameter_t *)pkbuf->data; + ogs_nas_authentication_response_parameter_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_authentication_response_parameter_t *)pkbuf->data; authentication_response_parameter->length = source->length; size = authentication_response_parameter->length + sizeof(authentication_response_parameter->length); @@ -2045,7 +2220,14 @@ int ogs_nas_eps_encode_lcs_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_lcs_indicator_t int ogs_nas_eps_decode_lcs_client_identity(ogs_nas_lcs_client_identity_t *lcs_client_identity, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_lcs_client_identity_t *source = (ogs_nas_lcs_client_identity_t *)pkbuf->data; + ogs_nas_lcs_client_identity_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_lcs_client_identity_t *)pkbuf->data; lcs_client_identity->length = source->length; size = lcs_client_identity->length + sizeof(lcs_client_identity->length); @@ -2118,7 +2300,14 @@ int ogs_nas_eps_encode_generic_message_container_type(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_eps_decode_generic_message_container(ogs_nas_generic_message_container_t *generic_message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_generic_message_container_t *source = (ogs_nas_generic_message_container_t *)pkbuf->data; + ogs_nas_generic_message_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_generic_message_container_t *)pkbuf->data; generic_message_container->length = be16toh(source->length); size = generic_message_container->length + sizeof(generic_message_container->length); @@ -2164,7 +2353,14 @@ int ogs_nas_eps_encode_generic_message_container(ogs_pkbuf_t *pkbuf, ogs_nas_gen int ogs_nas_eps_decode_voice_domain_preference_and_ue_usage_setting(ogs_nas_voice_domain_preference_and_ue_usage_setting_t *voice_domain_preference_and_ue_usage_setting, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_voice_domain_preference_and_ue_usage_setting_t *source = (ogs_nas_voice_domain_preference_and_ue_usage_setting_t *)pkbuf->data; + ogs_nas_voice_domain_preference_and_ue_usage_setting_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_voice_domain_preference_and_ue_usage_setting_t *)pkbuf->data; voice_domain_preference_and_ue_usage_setting->length = source->length; size = voice_domain_preference_and_ue_usage_setting->length + sizeof(voice_domain_preference_and_ue_usage_setting->length); @@ -2235,7 +2431,14 @@ int ogs_nas_eps_encode_guti_type(ogs_pkbuf_t *pkbuf, ogs_nas_guti_type_t *guti_t int ogs_nas_eps_decode_extended_drx_parameters(ogs_nas_extended_drx_parameters_t *extended_drx_parameters, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_drx_parameters_t *source = (ogs_nas_extended_drx_parameters_t *)pkbuf->data; + ogs_nas_extended_drx_parameters_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_drx_parameters_t *)pkbuf->data; extended_drx_parameters->length = source->length; size = extended_drx_parameters->length + sizeof(extended_drx_parameters->length); @@ -2274,7 +2477,14 @@ int ogs_nas_eps_encode_extended_drx_parameters(ogs_pkbuf_t *pkbuf, ogs_nas_exten int ogs_nas_eps_decode_dcn_id(ogs_nas_dcn_id_t *dcn_id, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_dcn_id_t *source = (ogs_nas_dcn_id_t *)pkbuf->data; + ogs_nas_dcn_id_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_dcn_id_t *)pkbuf->data; dcn_id->length = source->length; size = dcn_id->length + sizeof(dcn_id->length); @@ -2441,7 +2651,14 @@ int ogs_nas_eps_encode_csfb_response(ogs_pkbuf_t *pkbuf, ogs_nas_csfb_response_t int ogs_nas_eps_decode_hashmme(ogs_nas_hashmme_t *hashmme, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_hashmme_t *source = (ogs_nas_hashmme_t *)pkbuf->data; + ogs_nas_hashmme_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_hashmme_t *)pkbuf->data; hashmme->length = source->length; size = hashmme->length + sizeof(hashmme->length); @@ -2480,7 +2697,14 @@ int ogs_nas_eps_encode_hashmme(ogs_pkbuf_t *pkbuf, ogs_nas_hashmme_t *hashmme) int ogs_nas_eps_decode_replayed_nas_message_container(ogs_nas_replayed_nas_message_container_t *replayed_nas_message_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_replayed_nas_message_container_t *source = (ogs_nas_replayed_nas_message_container_t *)pkbuf->data; + ogs_nas_replayed_nas_message_container_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_replayed_nas_message_container_t *)pkbuf->data; replayed_nas_message_container->length = be16toh(source->length); size = replayed_nas_message_container->length + sizeof(replayed_nas_message_container->length); @@ -2558,7 +2782,14 @@ int ogs_nas_eps_encode_network_policy(ogs_pkbuf_t *pkbuf, ogs_nas_network_policy int ogs_nas_eps_decode_ue_additional_security_capability(ogs_nas_ue_additional_security_capability_t *ue_additional_security_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_additional_security_capability_t *source = (ogs_nas_ue_additional_security_capability_t *)pkbuf->data; + ogs_nas_ue_additional_security_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_additional_security_capability_t *)pkbuf->data; ue_additional_security_capability->length = source->length; size = ue_additional_security_capability->length + sizeof(ue_additional_security_capability->length); @@ -2597,7 +2828,14 @@ int ogs_nas_eps_encode_ue_additional_security_capability(ogs_pkbuf_t *pkbuf, ogs int ogs_nas_eps_decode_ue_status(ogs_nas_ue_status_t *ue_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_status_t *source = (ogs_nas_ue_status_t *)pkbuf->data; + ogs_nas_ue_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_status_t *)pkbuf->data; ue_status->length = source->length; size = ue_status->length + sizeof(ue_status->length); @@ -2670,7 +2908,14 @@ int ogs_nas_eps_encode_additional_information_requested(ogs_pkbuf_t *pkbuf, ogs_ int ogs_nas_eps_decode_ciphering_key_data(ogs_nas_ciphering_key_data_t *ciphering_key_data, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ciphering_key_data_t *source = (ogs_nas_ciphering_key_data_t *)pkbuf->data; + ogs_nas_ciphering_key_data_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ciphering_key_data_t *)pkbuf->data; ciphering_key_data->length = be16toh(source->length); size = ciphering_key_data->length + sizeof(ciphering_key_data->length); @@ -2716,7 +2961,14 @@ int ogs_nas_eps_encode_ciphering_key_data(ogs_pkbuf_t *pkbuf, ogs_nas_ciphering_ int ogs_nas_eps_decode_n1_ue_network_capability(ogs_nas_n1_ue_network_capability_t *n1_ue_network_capability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_n1_ue_network_capability_t *source = (ogs_nas_n1_ue_network_capability_t *)pkbuf->data; + ogs_nas_n1_ue_network_capability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_n1_ue_network_capability_t *)pkbuf->data; n1_ue_network_capability->length = source->length; size = n1_ue_network_capability->length + sizeof(n1_ue_network_capability->length); @@ -2755,7 +3007,14 @@ int ogs_nas_eps_encode_n1_ue_network_capability(ogs_pkbuf_t *pkbuf, ogs_nas_n1_u int ogs_nas_eps_decode_ue_radio_capability_id_availability(ogs_nas_ue_radio_capability_id_availability_t *ue_radio_capability_id_availability, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_radio_capability_id_availability_t *source = (ogs_nas_ue_radio_capability_id_availability_t *)pkbuf->data; + ogs_nas_ue_radio_capability_id_availability_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_radio_capability_id_availability_t *)pkbuf->data; ue_radio_capability_id_availability->length = source->length; size = ue_radio_capability_id_availability->length + sizeof(ue_radio_capability_id_availability->length); @@ -2794,7 +3053,14 @@ int ogs_nas_eps_encode_ue_radio_capability_id_availability(ogs_pkbuf_t *pkbuf, o int ogs_nas_eps_decode_ue_radio_capability_id_request(ogs_nas_ue_radio_capability_id_request_t *ue_radio_capability_id_request, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_radio_capability_id_request_t *source = (ogs_nas_ue_radio_capability_id_request_t *)pkbuf->data; + ogs_nas_ue_radio_capability_id_request_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_radio_capability_id_request_t *)pkbuf->data; ue_radio_capability_id_request->length = source->length; size = ue_radio_capability_id_request->length + sizeof(ue_radio_capability_id_request->length); @@ -2833,7 +3099,14 @@ int ogs_nas_eps_encode_ue_radio_capability_id_request(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_eps_decode_daylight_saving_time(ogs_nas_daylight_saving_time_t *daylight_saving_time, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_daylight_saving_time_t *source = (ogs_nas_daylight_saving_time_t *)pkbuf->data; + ogs_nas_daylight_saving_time_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_daylight_saving_time_t *)pkbuf->data; daylight_saving_time->length = source->length; size = daylight_saving_time->length + sizeof(daylight_saving_time->length); @@ -2872,7 +3145,14 @@ int ogs_nas_eps_encode_daylight_saving_time(ogs_pkbuf_t *pkbuf, ogs_nas_daylight int ogs_nas_eps_decode_ue_radio_capability_id(ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_radio_capability_id_t *source = (ogs_nas_ue_radio_capability_id_t *)pkbuf->data; + ogs_nas_ue_radio_capability_id_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_radio_capability_id_t *)pkbuf->data; ue_radio_capability_id->length = source->length; size = ue_radio_capability_id->length + sizeof(ue_radio_capability_id->length); @@ -2943,7 +3223,14 @@ int ogs_nas_eps_encode_ue_radio_capability_id_deletion_indication(ogs_pkbuf_t *p int ogs_nas_eps_decode_wus_assistance_information(ogs_nas_wus_assistance_information_t *wus_assistance_information, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_wus_assistance_information_t *source = (ogs_nas_wus_assistance_information_t *)pkbuf->data; + ogs_nas_wus_assistance_information_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_wus_assistance_information_t *)pkbuf->data; wus_assistance_information->length = source->length; size = wus_assistance_information->length + sizeof(wus_assistance_information->length); @@ -2982,7 +3269,14 @@ int ogs_nas_eps_encode_wus_assistance_information(ogs_pkbuf_t *pkbuf, ogs_nas_wu int ogs_nas_eps_decode_nb_s1_drx_parameter(ogs_nas_nb_s1_drx_parameter_t *nb_s1_drx_parameter, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nb_s1_drx_parameter_t *source = (ogs_nas_nb_s1_drx_parameter_t *)pkbuf->data; + ogs_nas_nb_s1_drx_parameter_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nb_s1_drx_parameter_t *)pkbuf->data; nb_s1_drx_parameter->length = source->length; size = nb_s1_drx_parameter->length + sizeof(nb_s1_drx_parameter->length); @@ -3021,7 +3315,14 @@ int ogs_nas_eps_encode_nb_s1_drx_parameter(ogs_pkbuf_t *pkbuf, ogs_nas_nb_s1_drx int ogs_nas_eps_decode_imsi_offset(ogs_nas_imsi_offset_t *imsi_offset, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_imsi_offset_t *source = (ogs_nas_imsi_offset_t *)pkbuf->data; + ogs_nas_imsi_offset_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_imsi_offset_t *)pkbuf->data; imsi_offset->length = source->length; size = imsi_offset->length + sizeof(imsi_offset->length); @@ -3060,7 +3361,14 @@ int ogs_nas_eps_encode_imsi_offset(ogs_pkbuf_t *pkbuf, ogs_nas_imsi_offset_t *im int ogs_nas_eps_decode_ue_request_type(ogs_nas_ue_request_type_t *ue_request_type, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_ue_request_type_t *source = (ogs_nas_ue_request_type_t *)pkbuf->data; + ogs_nas_ue_request_type_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_ue_request_type_t *)pkbuf->data; ue_request_type->length = source->length; size = ue_request_type->length + sizeof(ue_request_type->length); @@ -3099,7 +3407,14 @@ int ogs_nas_eps_encode_ue_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_ue_request_ty int ogs_nas_eps_decode_paging_restriction(ogs_nas_paging_restriction_t *paging_restriction, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_paging_restriction_t *source = (ogs_nas_paging_restriction_t *)pkbuf->data; + ogs_nas_paging_restriction_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_paging_restriction_t *)pkbuf->data; paging_restriction->length = source->length; size = paging_restriction->length + sizeof(paging_restriction->length); @@ -3138,7 +3453,14 @@ int ogs_nas_eps_encode_paging_restriction(ogs_pkbuf_t *pkbuf, ogs_nas_paging_res int ogs_nas_eps_decode_eps_additional_request_result(ogs_nas_eps_additional_request_result_t *eps_additional_request_result, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_additional_request_result_t *source = (ogs_nas_eps_additional_request_result_t *)pkbuf->data; + ogs_nas_eps_additional_request_result_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_additional_request_result_t *)pkbuf->data; eps_additional_request_result->length = source->length; size = eps_additional_request_result->length + sizeof(eps_additional_request_result->length); @@ -3279,7 +3601,14 @@ int ogs_nas_eps_encode_emm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_emm_cause_t *emm_ca int ogs_nas_eps_decode_access_point_name(ogs_nas_access_point_name_t *access_point_name, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_access_point_name_t *source = (ogs_nas_access_point_name_t *)pkbuf->data; + ogs_nas_access_point_name_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_access_point_name_t *)pkbuf->data; access_point_name->length = source->length; size = access_point_name->length + sizeof(access_point_name->length); @@ -3331,7 +3660,14 @@ int ogs_nas_eps_encode_access_point_name(ogs_pkbuf_t *pkbuf, ogs_nas_access_poin int ogs_nas_eps_decode_protocol_configuration_options(ogs_nas_protocol_configuration_options_t *protocol_configuration_options, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_protocol_configuration_options_t *source = (ogs_nas_protocol_configuration_options_t *)pkbuf->data; + ogs_nas_protocol_configuration_options_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_protocol_configuration_options_t *)pkbuf->data; protocol_configuration_options->length = source->length; size = protocol_configuration_options->length + sizeof(protocol_configuration_options->length); @@ -3370,7 +3706,14 @@ int ogs_nas_eps_encode_protocol_configuration_options(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_eps_decode_quality_of_service(ogs_nas_quality_of_service_t *quality_of_service, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_quality_of_service_t *source = (ogs_nas_quality_of_service_t *)pkbuf->data; + ogs_nas_quality_of_service_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_quality_of_service_t *)pkbuf->data; quality_of_service->length = source->length; size = quality_of_service->length + sizeof(quality_of_service->length); @@ -3441,7 +3784,14 @@ int ogs_nas_eps_encode_radio_priority(ogs_pkbuf_t *pkbuf, ogs_nas_radio_priority int ogs_nas_eps_decode_re_attempt_indicator(ogs_nas_re_attempt_indicator_t *re_attempt_indicator, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_re_attempt_indicator_t *source = (ogs_nas_re_attempt_indicator_t *)pkbuf->data; + ogs_nas_re_attempt_indicator_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_re_attempt_indicator_t *)pkbuf->data; re_attempt_indicator->length = source->length; size = re_attempt_indicator->length + sizeof(re_attempt_indicator->length); @@ -3514,7 +3864,14 @@ int ogs_nas_eps_encode_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_request_type_t * int ogs_nas_eps_decode_traffic_flow_aggregate_description(ogs_nas_traffic_flow_aggregate_description_t *traffic_flow_aggregate_description, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_traffic_flow_aggregate_description_t *source = (ogs_nas_traffic_flow_aggregate_description_t *)pkbuf->data; + ogs_nas_traffic_flow_aggregate_description_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_traffic_flow_aggregate_description_t *)pkbuf->data; traffic_flow_aggregate_description->length = source->length; size = traffic_flow_aggregate_description->length + sizeof(traffic_flow_aggregate_description->length); @@ -3553,7 +3910,14 @@ int ogs_nas_eps_encode_traffic_flow_aggregate_description(ogs_pkbuf_t *pkbuf, og int ogs_nas_eps_decode_traffic_flow_template(ogs_nas_traffic_flow_template_t *traffic_flow_template, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_traffic_flow_template_t *source = (ogs_nas_traffic_flow_template_t *)pkbuf->data; + ogs_nas_traffic_flow_template_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_traffic_flow_template_t *)pkbuf->data; traffic_flow_template->length = source->length; size = traffic_flow_template->length + sizeof(traffic_flow_template->length); @@ -3592,7 +3956,14 @@ int ogs_nas_eps_encode_traffic_flow_template(ogs_pkbuf_t *pkbuf, ogs_nas_traffic int ogs_nas_eps_decode_transaction_identifier(ogs_nas_transaction_identifier_t *transaction_identifier, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_transaction_identifier_t *source = (ogs_nas_transaction_identifier_t *)pkbuf->data; + ogs_nas_transaction_identifier_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_transaction_identifier_t *)pkbuf->data; transaction_identifier->length = source->length; size = transaction_identifier->length + sizeof(transaction_identifier->length); @@ -3663,7 +4034,14 @@ int ogs_nas_eps_encode_wlan_offload_acceptability(ogs_pkbuf_t *pkbuf, ogs_nas_wl int ogs_nas_eps_decode_nbifom_container(ogs_nas_nbifom_container_t *nbifom_container, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_nbifom_container_t *source = (ogs_nas_nbifom_container_t *)pkbuf->data; + ogs_nas_nbifom_container_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_nbifom_container_t *)pkbuf->data; nbifom_container->length = source->length; size = nbifom_container->length + sizeof(nbifom_container->length); @@ -3702,7 +4080,14 @@ int ogs_nas_eps_encode_nbifom_container(ogs_pkbuf_t *pkbuf, ogs_nas_nbifom_conta int ogs_nas_eps_decode_apn_aggregate_maximum_bit_rate(ogs_nas_apn_aggregate_maximum_bit_rate_t *apn_aggregate_maximum_bit_rate, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_apn_aggregate_maximum_bit_rate_t *source = (ogs_nas_apn_aggregate_maximum_bit_rate_t *)pkbuf->data; + ogs_nas_apn_aggregate_maximum_bit_rate_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_apn_aggregate_maximum_bit_rate_t *)pkbuf->data; apn_aggregate_maximum_bit_rate->length = source->length; size = apn_aggregate_maximum_bit_rate->length + sizeof(apn_aggregate_maximum_bit_rate->length); @@ -3741,7 +4126,14 @@ int ogs_nas_eps_encode_apn_aggregate_maximum_bit_rate(ogs_pkbuf_t *pkbuf, ogs_na int ogs_nas_eps_decode_header_compression_configuration(ogs_nas_header_compression_configuration_t *header_compression_configuration, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_header_compression_configuration_t *source = (ogs_nas_header_compression_configuration_t *)pkbuf->data; + ogs_nas_header_compression_configuration_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_header_compression_configuration_t *)pkbuf->data; header_compression_configuration->length = source->length; size = header_compression_configuration->length + sizeof(header_compression_configuration->length); @@ -3816,7 +4208,14 @@ int ogs_nas_eps_encode_control_plane_only_indication(ogs_pkbuf_t *pkbuf, ogs_nas int ogs_nas_eps_decode_extended_protocol_configuration_options(ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_protocol_configuration_options_t *source = (ogs_nas_extended_protocol_configuration_options_t *)pkbuf->data; + ogs_nas_extended_protocol_configuration_options_t *source = NULL; + + if (pkbuf->len < 2) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_protocol_configuration_options_t *)pkbuf->data; extended_protocol_configuration_options->length = be16toh(source->length); size = extended_protocol_configuration_options->length + sizeof(extended_protocol_configuration_options->length); @@ -3862,7 +4261,14 @@ int ogs_nas_eps_encode_extended_protocol_configuration_options(ogs_pkbuf_t *pkbu int ogs_nas_eps_decode_header_compression_configuration_status(ogs_nas_header_compression_configuration_status_t *header_compression_configuration_status, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_header_compression_configuration_status_t *source = (ogs_nas_header_compression_configuration_status_t *)pkbuf->data; + ogs_nas_header_compression_configuration_status_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_header_compression_configuration_status_t *)pkbuf->data; header_compression_configuration_status->length = source->length; size = header_compression_configuration_status->length + sizeof(header_compression_configuration_status->length); @@ -3901,7 +4307,14 @@ int ogs_nas_eps_encode_header_compression_configuration_status(ogs_pkbuf_t *pkbu int ogs_nas_eps_decode_serving_plmn_rate_control(ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_serving_plmn_rate_control_t *source = (ogs_nas_serving_plmn_rate_control_t *)pkbuf->data; + ogs_nas_serving_plmn_rate_control_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_serving_plmn_rate_control_t *)pkbuf->data; serving_plmn_rate_control->length = source->length; size = serving_plmn_rate_control->length + sizeof(serving_plmn_rate_control->length); @@ -3940,7 +4353,14 @@ int ogs_nas_eps_encode_serving_plmn_rate_control(ogs_pkbuf_t *pkbuf, ogs_nas_ser int ogs_nas_eps_decode_extended_apn_aggregate_maximum_bit_rate(ogs_nas_extended_apn_aggregate_maximum_bit_rate_t *extended_apn_aggregate_maximum_bit_rate, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_apn_aggregate_maximum_bit_rate_t *source = (ogs_nas_extended_apn_aggregate_maximum_bit_rate_t *)pkbuf->data; + ogs_nas_extended_apn_aggregate_maximum_bit_rate_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_apn_aggregate_maximum_bit_rate_t *)pkbuf->data; extended_apn_aggregate_maximum_bit_rate->length = source->length; size = extended_apn_aggregate_maximum_bit_rate->length + sizeof(extended_apn_aggregate_maximum_bit_rate->length); @@ -4011,7 +4431,14 @@ int ogs_nas_eps_encode_connectivity_type(ogs_pkbuf_t *pkbuf, ogs_nas_connectivit int ogs_nas_eps_decode_eps_quality_of_service(ogs_nas_eps_quality_of_service_t *eps_quality_of_service, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_eps_quality_of_service_t *source = (ogs_nas_eps_quality_of_service_t *)pkbuf->data; + ogs_nas_eps_quality_of_service_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_eps_quality_of_service_t *)pkbuf->data; eps_quality_of_service->length = source->length; size = eps_quality_of_service->length + sizeof(eps_quality_of_service->length); @@ -4050,7 +4477,14 @@ int ogs_nas_eps_encode_eps_quality_of_service(ogs_pkbuf_t *pkbuf, ogs_nas_eps_qu int ogs_nas_eps_decode_extended_quality_of_service(ogs_nas_extended_quality_of_service_t *extended_quality_of_service, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_extended_quality_of_service_t *source = (ogs_nas_extended_quality_of_service_t *)pkbuf->data; + ogs_nas_extended_quality_of_service_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_extended_quality_of_service_t *)pkbuf->data; extended_quality_of_service->length = source->length; size = extended_quality_of_service->length + sizeof(extended_quality_of_service->length); @@ -4223,7 +4657,14 @@ int ogs_nas_eps_encode_llc_service_access_point_identifier(ogs_pkbuf_t *pkbuf, o int ogs_nas_eps_decode_packet_flow_identifier(ogs_nas_packet_flow_identifier_t *packet_flow_identifier, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_packet_flow_identifier_t *source = (ogs_nas_packet_flow_identifier_t *)pkbuf->data; + ogs_nas_packet_flow_identifier_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_packet_flow_identifier_t *)pkbuf->data; packet_flow_identifier->length = source->length; size = packet_flow_identifier->length + sizeof(packet_flow_identifier->length); @@ -4262,7 +4703,14 @@ int ogs_nas_eps_encode_packet_flow_identifier(ogs_pkbuf_t *pkbuf, ogs_nas_packet int ogs_nas_eps_decode_pdn_address(ogs_nas_pdn_address_t *pdn_address, ogs_pkbuf_t *pkbuf) { int size = 0; - ogs_nas_pdn_address_t *source = (ogs_nas_pdn_address_t *)pkbuf->data; + ogs_nas_pdn_address_t *source = NULL; + + if (pkbuf->len < 1) { + ogs_error("Not enough pkbuf [len:%d]", pkbuf->len); + return -1; + } + + source = (ogs_nas_pdn_address_t *)pkbuf->data; pdn_address->length = source->length; size = pdn_address->length + sizeof(pdn_address->length); diff --git a/lib/nas/eps/support/nas-message.py b/lib/nas/eps/support/nas-message.py index 19b1354bb..e882cf60a 100644 --- a/lib/nas/eps/support/nas-message.py +++ b/lib/nas/eps/support/nas-message.py @@ -461,7 +461,12 @@ for (k, v) in sorted_type_list: f.write("int ogs_nas_eps_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf)\n" % (v_lower(k), v_lower(k), v_lower(k))) f.write("{\n") f.write(" int size = 0;\n") - f.write(" ogs_nas_%s_t *source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % (v_lower(k), v_lower(k))) + f.write(" ogs_nas_%s_t *source = NULL;\n\n" % v_lower(k)) + f.write(" if (pkbuf->len < 2) {\n") + f.write(" ogs_error(\"Not enough pkbuf [len:%d]\", pkbuf->len);\n") + f.write(" return -1;\n") + f.write(" }\n\n") + f.write(" source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % v_lower(k)) f.write(" %s->length = be16toh(source->length);\n" % v_lower(k)) f.write(" size = %s->length + sizeof(%s->length);\n\n" % (v_lower(k), v_lower(k))) f.write(" if (ogs_pkbuf_pull(pkbuf, size) == NULL) {\n") @@ -494,7 +499,12 @@ for (k, v) in sorted_type_list: f.write("int ogs_nas_eps_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf)\n" % (v_lower(k), v_lower(k), v_lower(k))) f.write("{\n") f.write(" int size = 0;\n") - f.write(" ogs_nas_%s_t *source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % (v_lower(k), v_lower(k))) + f.write(" ogs_nas_%s_t *source = NULL;\n\n" % v_lower(k)) + f.write(" if (pkbuf->len < 1) {\n") + f.write(" ogs_error(\"Not enough pkbuf [len:%d]\", pkbuf->len);\n") + f.write(" return -1;\n") + f.write(" }\n\n") + f.write(" source = (ogs_nas_%s_t *)pkbuf->data;\n\n" % v_lower(k)) f.write(" %s->length = source->length;\n" % v_lower(k)) f.write(" size = %s->length + sizeof(%s->length);\n\n" % (v_lower(k), v_lower(k))) f.write(" if (ogs_pkbuf_pull(pkbuf, size) == NULL) {\n") diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index a87661635..74ecf0b07 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -26,7 +26,6 @@ static int context_initialized = 0; static OGS_POOL(ogs_pfcp_node_pool, ogs_pfcp_node_t); -static OGS_POOL(ogs_pfcp_sess_pool, ogs_pfcp_sess_t); static OGS_POOL(ogs_pfcp_far_pool, ogs_pfcp_far_t); static OGS_POOL(ogs_pfcp_urr_pool, ogs_pfcp_urr_t); static OGS_POOL(ogs_pfcp_qer_pool, ogs_pfcp_qer_t); @@ -55,8 +54,6 @@ void ogs_pfcp_context_init(void) ogs_pool_init(&ogs_pfcp_node_pool, ogs_app()->pool.nf); - ogs_pool_init(&ogs_pfcp_sess_pool, ogs_app()->pool.sess); - ogs_pool_init(&ogs_pfcp_far_pool, ogs_app()->pool.sess * OGS_MAX_NUM_OF_FAR); ogs_pool_init(&ogs_pfcp_urr_pool, @@ -116,7 +113,6 @@ void ogs_pfcp_context_final(void) ogs_pool_final(&ogs_pfcp_pdr_teid_pool); ogs_free(pdr_random_to_index); - ogs_pool_final(&ogs_pfcp_sess_pool); ogs_pool_final(&ogs_pfcp_far_pool); ogs_pool_final(&ogs_pfcp_urr_pool); ogs_pool_final(&ogs_pfcp_qer_pool); @@ -371,6 +367,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) server_key); } + /* Add address information */ addr = NULL; for (i = 0; i < num; i++) { rv = ogs_addaddrinfo(&addr, @@ -378,20 +375,34 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) ogs_assert(rv == OGS_OK); } + /* Add each address as a separate socknode */ if (addr) { - if (ogs_global_conf()-> - parameter.no_ipv4 == 0) - ogs_socknode_add( - &self.pfcp_list, AF_INET, addr, - is_option ? &option : NULL); - if (ogs_global_conf()-> - parameter.no_ipv6 == 0) - ogs_socknode_add( - &self.pfcp_list6, AF_INET6, addr, - is_option ? &option : NULL); + ogs_sockaddr_t *current = addr; + while (current) { + if (current->ogs_sa_family == + AF_INET && + ogs_global_conf()-> + parameter.no_ipv4 == 0) { + ogs_socknode_add(&self.pfcp_list, + AF_INET, current, + is_option ? + &option : NULL); + } + if (current->ogs_sa_family == + AF_INET6 && + ogs_global_conf()-> + parameter.no_ipv6 == 0) { + ogs_socknode_add(&self.pfcp_list6, + AF_INET6, current, + is_option ? + &option : NULL); + } + current = current->next; + } ogs_freeaddrinfo(addr); } + /* Process advertise addresses if needed */ addr = NULL; for (i = 0; i < num_of_advertise; i++) { rv = ogs_addaddrinfo(&addr, @@ -420,6 +431,7 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) ogs_freeaddrinfo(addr); } + /* Bind to device if specified */ if (dev) { rv = ogs_socknode_probe( ogs_global_conf()-> @@ -852,20 +864,43 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) return OGS_OK; } -ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list) +/****************************************************************************** + * ogs_pfcp_node_new() + * - Initialize node_id.type to OGS_PFCP_NODE_ID_UNKNOWN + * - So the node can later be updated with a real Node ID via + * ogs_pfcp_node_merge() once we learn it from PFCP messages. + ******************************************************************************/ +ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *config_addr) { + int rv; ogs_pfcp_node_t *node = NULL; - ogs_assert(sa_list); - ogs_pool_alloc(&ogs_pfcp_node_pool, &node); if (!node) { - ogs_error("No memory: ogs_pool_alloc() failed"); + ogs_error("No memory: ogs_pool_alloc() failed [%s]", + ogs_sockaddr_to_string_static(config_addr)); return NULL; } memset(node, 0, sizeof(ogs_pfcp_node_t)); - node->sa_list = sa_list; + /* Store config_addr, if any */ + node->config_addr = config_addr; + + /* If config_addr is given, copy it immediately into addr_list */ + if (config_addr) { + rv = ogs_copyaddrinfo(&node->addr_list, config_addr); + if (rv != OGS_OK) { + ogs_error("ogs_copyaddrinfo() failed"); + ogs_pool_free(&ogs_pfcp_node_pool, node); + return NULL; + } + } + + /* + * Initialize node->node_id to UNKNOWN, meaning "no Node ID assigned yet". + */ + memset(&node->node_id, 0, sizeof(node->node_id)); + node->node_id.type = OGS_PFCP_NODE_ID_UNKNOWN; ogs_list_init(&node->local_list); ogs_list_init(&node->remote_list); @@ -883,49 +918,199 @@ void ogs_pfcp_node_free(ogs_pfcp_node_t *node) ogs_pfcp_xact_delete_all(node); - ogs_freeaddrinfo(node->sa_list); + ogs_freeaddrinfo(node->config_addr); + ogs_freeaddrinfo(node->addr_list); + ogs_pool_free(&ogs_pfcp_node_pool, node); } -ogs_pfcp_node_t *ogs_pfcp_node_add( - ogs_list_t *list, ogs_sockaddr_t *addr) +/****************************************************************************** + * ogs_pfcp_node_add() + * - Create a new PFCP node, then call ogs_pfcp_node_merge() to handle + * IPv4/IPv6 or FQDN logic. + ******************************************************************************/ +ogs_pfcp_node_t *ogs_pfcp_node_add(ogs_list_t *list, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from) { ogs_pfcp_node_t *node = NULL; - ogs_sockaddr_t *new = NULL; ogs_assert(list); - ogs_assert(addr); + ogs_assert(node_id && from); - ogs_assert(OGS_OK == ogs_copyaddrinfo(&new, addr)); - node = ogs_pfcp_node_new(new); - if (!node) { - ogs_error("No memory : ogs_pfcp_node_new() failed"); - ogs_freeaddrinfo(new); + /* + * We only handle IPv4, IPv6, and FQDN types here. If the incoming + * node_id has any other type, we treat it as invalid. This ensures + * we do not merge a node with an unsupported PFCP Node ID. + */ + if (node_id->type != OGS_PFCP_NODE_ID_IPV4 && + node_id->type != OGS_PFCP_NODE_ID_IPV6 && + node_id->type != OGS_PFCP_NODE_ID_FQDN) { + ogs_error("Invalid PFCP Node Type = %d", node_id->type); return NULL; } - ogs_assert(node); - memcpy(&node->addr, new, sizeof node->addr); + /* Create node with no config_addr initially */ + node = ogs_pfcp_node_new(NULL); + if (!node) { + ogs_error("No memory: ogs_pfcp_node_add() failed node_id:%s from:%s", + ogs_pfcp_node_id_to_string_static(node_id), + ogs_sockaddr_to_string_static(from)); + return NULL; + } + + /* Set node->node_id, reset last_dns_refresh. */ + memcpy(&node->node_id, node_id, sizeof(node->node_id)); + node->last_dns_refresh = 0; + + /* Merge addresses => fill node->addr_list if conditions are met */ + if (ogs_pfcp_node_merge(node, node_id, from) != OGS_OK) { + ogs_error("ogs_pfcp_node_merge() failed node_id [%s] from [%s]", + ogs_pfcp_node_id_to_string_static(node_id), + ogs_sockaddr_to_string_static(from)); + ogs_pool_free(&ogs_pfcp_node_pool, node); + return NULL; + } ogs_list_add(list, node); return node; } -ogs_pfcp_node_t *ogs_pfcp_node_find( - ogs_list_t *list, ogs_sockaddr_t *addr) +/****************************************************************************** + * ogs_pfcp_node_find() + * - No DNS logic here. Merely finds a node by node_id (if provided) and + * checks if 'from' address is in node->addr_list. + ******************************************************************************/ +ogs_pfcp_node_t *ogs_pfcp_node_find(ogs_list_t *list, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from) { - ogs_pfcp_node_t *node = NULL; + ogs_pfcp_node_t *cur; ogs_assert(list); - ogs_assert(addr); + ogs_assert(node_id || from); - ogs_list_for_each(list, node) { - if (ogs_sockaddr_is_equal(&node->addr, addr) == true) - break; + ogs_list_for_each(list, cur) { + /* + * If the node currently has a known Node ID (not UNKNOWN) + * and the caller provided a node_id to match, then compare them. + * If they do not match, skip this node. This allows config-based nodes + * (with an UNKNOWN node_id) to be found by IP address alone, + * while nodes with a definite ID must match the incoming node_id. + */ + if (cur->node_id.type != OGS_PFCP_NODE_ID_UNKNOWN && node_id) { + if (!ogs_pfcp_node_id_compare(&cur->node_id, node_id)) + continue; + } + if (!from) + return cur; + + /* Check if 'from' is in cur->addr_list. */ + if (ogs_sockaddr_check_any_match(cur->addr_list, NULL, + from, /* compare_port= */ true)) { + return cur; + } } - return node; + /* No match found. */ + return NULL; +} + +/****************************************************************************** + * ogs_pfcp_node_merge(): + * - If node_id changes to FQDN, we check last_dns_refresh. + * => If 0, do an immediate DNS resolution (first time). + * => If >= 300 seconds passed, do a periodic refresh. + * => Otherwise, skip. + * - If node_id changes to IPv4/IPv6, convert IP addresses immediately. + * - Merge the 'from' address into addr_list if provided. + ******************************************************************************/ +int ogs_pfcp_node_merge(ogs_pfcp_node_t *node, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from) +{ + ogs_sockaddr_t single; + ogs_sockaddr_t *tmp_list = NULL; + + ogs_assert(node); + ogs_assert(node_id || from); + + if (node_id) { + /* + * We only handle IPv4, IPv6, and FQDN types here. If the incoming + * node_id has any other type, we treat it as invalid. This ensures + * we do not merge a node with an unsupported PFCP Node ID. + */ + if (node_id->type != OGS_PFCP_NODE_ID_IPV4 && + node_id->type != OGS_PFCP_NODE_ID_IPV6 && + node_id->type != OGS_PFCP_NODE_ID_FQDN) { + ogs_error("Invalid PFCP Node Type = %d", node_id->type); + return OGS_ERROR; + } + + /* Check if node_id is different from node->node_id. */ + if (!ogs_pfcp_node_id_compare(&node->node_id, node_id)) { + /* Update the node's ID and reset the refresh timestamp. */ + memcpy(&node->node_id, node_id, sizeof(node->node_id)); + node->last_dns_refresh = 0; + } + + /* If FQDN, do a DNS lookup (immediate or periodic). */ + if (node->node_id.type == OGS_PFCP_NODE_ID_FQDN) { +/* + * We perform a DNS resolution if 'last_dns_refresh' is zero, which means + * this FQDN node has never been resolved yet (first-time resolution), or if + * at least 300 seconds have passed since the last refresh. Without checking + * '== 0', a newly created FQDN node might skip resolution if 'now' is less + * than the 300-second threshold. + */ + ogs_time_t now = ogs_time_now(); + +/* For 300-second refresh interval in microseconds. */ +#define OGS_PFCP_NODE_DNS_REFRESH_INTERVAL \ + ((ogs_time_t)(300) * OGS_USEC_PER_SEC) + if (node->last_dns_refresh == 0 || + (now - node->last_dns_refresh) >= + OGS_PFCP_NODE_DNS_REFRESH_INTERVAL) { + + tmp_list = ogs_pfcp_node_id_to_addrinfo(&node->node_id); + if (!tmp_list) { + ogs_error("DNS resolution failed for FQDN [%s]", + node->node_id.fqdn); + return OGS_ERROR; + } + + ogs_freeaddrinfo(node->addr_list); + node->addr_list = tmp_list; + node->last_dns_refresh = now; + tmp_list = NULL; + } + } + /* If IPv4/IPv6, convert immediately. */ + else if (node->node_id.type == OGS_PFCP_NODE_ID_IPV4 || + node->node_id.type == OGS_PFCP_NODE_ID_IPV6) { + tmp_list = ogs_pfcp_node_id_to_addrinfo(&node->node_id); + if (!tmp_list) { + ogs_error("Failed to convert node ID to address info"); + return OGS_ERROR; + } + ogs_merge_addrinfo(&node->addr_list, tmp_list); + ogs_freeaddrinfo(tmp_list); + tmp_list = NULL; + } + else { + /* Not IPv4, IPv6, or FQDN => invalid node type. */ + ogs_error("Invalid Node ID type [%d]", node->node_id.type); + return OGS_ERROR; + } + } + + /* Merge 'from' into addr_list if provided. */ + if (from) { + memcpy(&single, from, sizeof(single)); + single.next = NULL; + ogs_merge_addrinfo(&node->addr_list, &single); + } + + return OGS_OK; } void ogs_pfcp_node_remove(ogs_list_t *list, ogs_pfcp_node_t *node) @@ -947,6 +1132,37 @@ void ogs_pfcp_node_remove_all(ogs_list_t *list) ogs_pfcp_node_remove(list, node); } +/****************************************************************************** + * Compare two node IDs for equality. Returns true if they match, else false. + ******************************************************************************/ +bool ogs_pfcp_node_id_compare( + const ogs_pfcp_node_id_t *id1, const ogs_pfcp_node_id_t *id2) +{ + if (id1->type != id2->type) + return false; /* Types do not match */ + + switch (id1->type) { + case OGS_PFCP_NODE_ID_IPV4: + if (id1->addr != id2->addr) return false; + return true; + + case OGS_PFCP_NODE_ID_IPV6: + if (memcmp(id1->addr6, id2->addr6, OGS_IPV6_LEN) != 0) + return false; + return true; + + case OGS_PFCP_NODE_ID_FQDN: + if (strcmp(id1->fqdn, id2->fqdn) != 0) + return false; + return true; + + default: + ogs_error("Unexpected Node Type [%d]", id1->type); + ogs_abort(); + return false; /* Unknown types do not match */ + } +} + ogs_gtpu_resource_t *ogs_pfcp_find_gtpu_resource(ogs_list_t *list, char *dnn, ogs_pfcp_interface_t source_interface) { @@ -1144,6 +1360,7 @@ void ogs_pfcp_pdr_swap_teid(ogs_pfcp_pdr_t *pdr) int i = 0; ogs_assert(pdr); + ogs_assert(!pdr->f_teid.ch); ogs_assert(pdr->f_teid.teid > 0 && pdr->f_teid.teid <= ogs_pfcp_pdr_teid_pool.size); @@ -1871,10 +2088,10 @@ void ogs_pfcp_bar_delete(ogs_pfcp_bar_t *bar) if (bar->id_node) ogs_pool_free(&bar->sess->bar_id_pool, bar->id_node); - ogs_pool_free(&ogs_pfcp_bar_pool, bar); - bar->sess = NULL; sess->bar = NULL; + + ogs_pool_free(&ogs_pfcp_bar_pool, bar); } ogs_pfcp_rule_t *ogs_pfcp_rule_add(ogs_pfcp_pdr_t *pdr) diff --git a/lib/pfcp/context.h b/lib/pfcp/context.h index 609d74ed8..70b253be3 100644 --- a/lib/pfcp/context.h +++ b/lib/pfcp/context.h @@ -84,10 +84,20 @@ typedef struct ogs_pfcp_context_s { typedef struct ogs_pfcp_node_s { ogs_lnode_t lnode; /* A node of list_t */ - ogs_sockaddr_t *sa_list; /* Socket Address List Candidate */ + ogs_sockaddr_t *config_addr; /* Configured addresses */ + ogs_pfcp_node_id_t node_id; /* PFCP node ID */ - ogs_sock_t *sock; /* Socket Instance */ - ogs_sockaddr_t addr; /* Remote Address */ + /* List of addresses:: final merged address list */ + ogs_sockaddr_t *addr_list; + + /* + * Iterator for round-robin sendto operations. + * Points to the current address in the round-robin sequence. + */ + ogs_sockaddr_t *current_addr; + + /* Timestamp of last DNS refresh for FQDN nodes. */ + ogs_time_t last_dns_refresh; ogs_list_t local_list; ogs_list_t remote_list; @@ -399,15 +409,19 @@ void ogs_pfcp_context_final(void); ogs_pfcp_context_t *ogs_pfcp_self(void); int ogs_pfcp_context_parse_config(const char *local, const char *remote); -ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list); +ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *config_addr); void ogs_pfcp_node_free(ogs_pfcp_node_t *node); -ogs_pfcp_node_t *ogs_pfcp_node_add( - ogs_list_t *list, ogs_sockaddr_t *addr); -ogs_pfcp_node_t *ogs_pfcp_node_find( - ogs_list_t *list, ogs_sockaddr_t *addr); +ogs_pfcp_node_t *ogs_pfcp_node_add(ogs_list_t *list, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from); +ogs_pfcp_node_t *ogs_pfcp_node_find(ogs_list_t *list, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from); +int ogs_pfcp_node_merge(ogs_pfcp_node_t *node, + ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from); void ogs_pfcp_node_remove(ogs_list_t *list, ogs_pfcp_node_t *node); void ogs_pfcp_node_remove_all(ogs_list_t *list); +bool ogs_pfcp_node_id_compare( + const ogs_pfcp_node_id_t *id1, const ogs_pfcp_node_id_t *id2); ogs_gtpu_resource_t *ogs_pfcp_find_gtpu_resource(ogs_list_t *list, char *dnn, ogs_pfcp_interface_t source_interface); diff --git a/lib/pfcp/handler.c b/lib/pfcp/handler.c index 0ab5cfeb0..a8e24ce6a 100644 --- a/lib/pfcp/handler.c +++ b/lib/pfcp/handler.c @@ -130,14 +130,9 @@ bool ogs_pfcp_cp_handle_association_setup_request( } } - if (node->up_function_features.ftup == 0) { - char buf[OGS_ADDRSTRLEN]; - ogs_sockaddr_t *addr = node->sa_list; - ogs_assert(addr); - - ogs_warn("F-TEID allocation/release not supported with peer [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); - } + if (node->up_function_features.ftup == 0) + ogs_warn("F-TEID allocation/release not supported with peer %s", + ogs_sockaddr_to_string_static(node->addr_list)); return true; } @@ -182,14 +177,9 @@ bool ogs_pfcp_cp_handle_association_setup_response( } } - if (node->up_function_features.ftup == 0) { - char buf[OGS_ADDRSTRLEN]; - ogs_sockaddr_t *addr = node->sa_list; - ogs_assert(addr); - - ogs_warn("F-TEID allocation/release not supported with peer [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); - } + if (node->up_function_features.ftup == 0) + ogs_warn("F-TEID allocation/release not supported with peer %s", + ogs_sockaddr_to_string_static(node->addr_list)); return true; } diff --git a/lib/pfcp/meson.build b/lib/pfcp/meson.build index 910b50828..50b524852 100644 --- a/lib/pfcp/meson.build +++ b/lib/pfcp/meson.build @@ -45,6 +45,7 @@ libpfcp_sources = files(''' xact.h context.h rule-match.h + util.h message.c types.c @@ -55,6 +56,7 @@ libpfcp_sources = files(''' xact.c context.c rule-match.c + util.c '''.split()) libpfcp_inc = include_directories('.') diff --git a/lib/pfcp/ogs-pfcp.h b/lib/pfcp/ogs-pfcp.h index 7403ba80d..e6ea050a3 100644 --- a/lib/pfcp/ogs-pfcp.h +++ b/lib/pfcp/ogs-pfcp.h @@ -43,6 +43,7 @@ #include "pfcp/path.h" #include "pfcp/xact.h" #include "pfcp/handler.h" +#include "pfcp/util.h" #ifdef __cplusplus extern "C" { diff --git a/lib/pfcp/path.c b/lib/pfcp/path.c index 203c4d5e7..14c9a6986 100644 --- a/lib/pfcp/path.c +++ b/lib/pfcp/path.c @@ -36,69 +36,6 @@ ogs_sock_t *ogs_pfcp_server(ogs_socknode_t *node) return pfcp; } -int ogs_pfcp_connect( - ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_pfcp_node_t *node) -{ - ogs_sockaddr_t *addr; - char buf[OGS_ADDRSTRLEN]; - - ogs_assert(ipv4 || ipv6); - ogs_assert(node); - ogs_assert(node->sa_list); - - addr = node->sa_list; - while (addr) { - ogs_sock_t *sock = NULL; - - if (addr->ogs_sa_family == AF_INET) - sock = ipv4; - else if (addr->ogs_sa_family == AF_INET6) - sock = ipv6; - else - ogs_assert_if_reached(); - - if (sock) { - ogs_info("ogs_pfcp_connect() [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); - - node->sock = sock; - memcpy(&node->addr, addr, sizeof node->addr); - break; - } - - addr = addr->next; - } - - if (addr == NULL) { - ogs_error("ogs_pfcp_connect() [%s]:%d failed", - OGS_ADDR(node->sa_list, buf), OGS_PORT(node->sa_list)); - ogs_error("Please check the IP version between SMF and UPF nodes."); - return OGS_ERROR; - } - - return OGS_OK; -} - -int ogs_pfcp_send(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf) -{ - ssize_t sent; - ogs_sock_t *sock = NULL; - - ogs_assert(node); - ogs_assert(pkbuf); - sock = node->sock; - ogs_assert(sock); - - sent = ogs_send(sock->fd, pkbuf->data, pkbuf->len, 0); - if (sent < 0 || sent != pkbuf->len) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "ogs_pfcp_send() failed"); - return OGS_ERROR; - } - - return OGS_OK; -} - int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf) { ssize_t sent; @@ -107,11 +44,34 @@ int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf) ogs_assert(node); ogs_assert(pkbuf); - sock = node->sock; - ogs_assert(sock); - addr = &node->addr; + ogs_assert(node->addr_list); + + /* Initialize round-robin iterator if needed */ + if (node->current_addr == NULL) { + node->current_addr = node->addr_list; + } + addr = node->current_addr; ogs_assert(addr); + if (addr->ogs_sa_family == AF_INET) { + sock = ogs_pfcp_self()->pfcp_sock; + if (!sock) { + ogs_error("IPv4 socket (pfcp_sock) is not available. " + "Ensure that 'pfcp.server.address: 127.0.0.1' " + "is set in the YAML configuration file."); + return OGS_ERROR; + } + } else if (addr->ogs_sa_family == AF_INET6) { + sock = ogs_pfcp_self()->pfcp_sock6; + if (!sock) { + ogs_error("IPv6 socket (pfcp_sock) is not available. " + "Ensure that 'pfcp.server.address: [::1]' " + "is set in the YAML configuration file."); + return OGS_ERROR; + } + } else + ogs_assert_if_reached(); + sent = ogs_sendto(sock->fd, pkbuf->data, pkbuf->len, 0, addr); if (sent < 0 || sent != pkbuf->len) { if (ogs_socket_errno != OGS_EAGAIN) { @@ -125,6 +85,13 @@ int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf) return OGS_ERROR; } + /* Move to next address in round-robin sequence */ + if (node->current_addr->next) + node->current_addr = node->current_addr->next; + else + /* If end of list reached, wrap around to the start */ + node->current_addr = node->addr_list; + return OGS_OK; } diff --git a/lib/pfcp/path.h b/lib/pfcp/path.h index d7f6c3278..eae2605fd 100644 --- a/lib/pfcp/path.h +++ b/lib/pfcp/path.h @@ -56,10 +56,6 @@ extern "C" { typedef struct ogs_pfcp_xact_s ogs_pfcp_xact_t; ogs_sock_t *ogs_pfcp_server(ogs_socknode_t *node); -int ogs_pfcp_connect( - ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_pfcp_node_t *node); - -int ogs_pfcp_send(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf); int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf); ogs_pkbuf_t *ogs_pfcp_handle_echo_req(ogs_pkbuf_t *pkt); diff --git a/lib/pfcp/types.h b/lib/pfcp/types.h index 433382f5d..cbe9df7de 100644 --- a/lib/pfcp/types.h +++ b/lib/pfcp/types.h @@ -550,9 +550,17 @@ typedef struct ogs_pfcp_outer_header_removal_s { uint8_t gtpu_extheader_deletion; } ogs_pfcp_outer_header_removal_t; +/****************************************************************************** + * PFCP Node ID structure + ******************************************************************************/ #define OGS_PFCP_NODE_ID_IPV4 0 #define OGS_PFCP_NODE_ID_IPV6 1 #define OGS_PFCP_NODE_ID_FQDN 2 + +/****************************************************************************** + * Add this line to define the UNKNOWN type. We use '3' since 0,1,2 are taken. + ******************************************************************************/ +#define OGS_PFCP_NODE_ID_UNKNOWN 0xf typedef struct ogs_pfcp_node_id_s { ED2(uint8_t spare:4;, uint8_t type:4;) diff --git a/lib/pfcp/util.c b/lib/pfcp/util.c new file mode 100644 index 000000000..295f1211c --- /dev/null +++ b/lib/pfcp/util.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2025 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ogs-pfcp.h" + +/* + * Requirements of Node ID: + * NONE : Node ID must not be present + * OPTIONAL : Node ID may or may not be present + * MANDATORY : Node ID must be present + */ +#define OGS_PFCP_NODE_ID_NONE 0 +#define OGS_PFCP_NODE_ID_OPTIONAL 1 +#define OGS_PFCP_NODE_ID_MANDATORY 2 + +/* + * This function extracts the PFCP Node ID from the given PFCP message. + * It determines the Node ID field location and requirement based on + * the message type. Then it validates presence and copies data into + * 'node_id'. If Node ID is not consistent with the requirement, an + * error status is returned. + */ +ogs_pfcp_status_e +ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message, + ogs_pfcp_node_id_t *node_id) +{ + + /* For C89 compliance, all variables are declared upfront. */ + ogs_pfcp_tlv_node_id_t *tlv_node_id = NULL; + int requirement = OGS_PFCP_NODE_ID_NONE; + ogs_pfcp_status_e status = OGS_PFCP_STATUS_SUCCESS; + + /* Validate input pointers */ + ogs_assert(message); + ogs_assert(node_id); + + /* Initialize the output structure */ + memset(node_id, 0, sizeof(*node_id)); + + /* Determine the location of node_id TLV and requirement */ + switch (message->h.type) { + case OGS_PFCP_PFD_MANAGEMENT_REQUEST_TYPE: + tlv_node_id = &message->pfcp_pfd_management_request.node_id; + requirement = OGS_PFCP_NODE_ID_OPTIONAL; + break; + + case OGS_PFCP_PFD_MANAGEMENT_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_pfd_management_response.node_id; + requirement = OGS_PFCP_NODE_ID_OPTIONAL; + break; + + case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: + tlv_node_id = &message->pfcp_association_setup_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_association_setup_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_ASSOCIATION_UPDATE_REQUEST_TYPE: + tlv_node_id = &message->pfcp_association_update_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_ASSOCIATION_UPDATE_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_association_update_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_ASSOCIATION_RELEASE_REQUEST_TYPE: + tlv_node_id = &message->pfcp_association_release_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_ASSOCIATION_RELEASE_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_association_release_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_NODE_REPORT_REQUEST_TYPE: + tlv_node_id = &message->pfcp_node_report_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_NODE_REPORT_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_node_report_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_SET_DELETION_REQUEST_TYPE: + tlv_node_id = &message->pfcp_session_set_deletion_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_SET_DELETION_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_session_set_deletion_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_SET_MODIFICATION_REQUEST_TYPE: + tlv_node_id = &message->pfcp_session_set_modification_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_SET_MODIFICATION_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_session_set_modification_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: + tlv_node_id = &message->pfcp_session_establishment_request.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: + tlv_node_id = &message->pfcp_session_establishment_response.node_id; + requirement = OGS_PFCP_NODE_ID_MANDATORY; + break; + + case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: + tlv_node_id = &message->pfcp_session_modification_request.node_id; + requirement = OGS_PFCP_NODE_ID_OPTIONAL; + break; + + /* Add other message types with node_id here as needed */ + + case OGS_PFCP_HEARTBEAT_REQUEST_TYPE: + case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE: + case OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE: + case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE: + case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: + case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: + case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE: + case OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE: + /* Node ID must not be present for these messages */ + requirement = OGS_PFCP_NODE_ID_NONE; + break; + + default: + /* Unknown message type */ + ogs_error("Unknown message type %d", message->h.type); + return OGS_PFCP_ERROR_UNKNOWN_MESSAGE; + } + + /* Check requirement vs. tlv_node_id existence */ + switch (requirement) { + case OGS_PFCP_NODE_ID_MANDATORY: + /* Must have tlv_node_id. presence must be 1. */ + ogs_assert(tlv_node_id); + if (!tlv_node_id->presence) { + status = OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT; + goto done; + } + break; + + case OGS_PFCP_NODE_ID_OPTIONAL: + /* + * Must have tlv_node_id. presence=1 => real Node ID + * presence=0 => no Node ID + */ + ogs_assert(tlv_node_id); + if (!tlv_node_id->presence) { + status = OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT; + goto done; + } + break; + + case OGS_PFCP_NODE_ID_NONE: + /* Must be NULL => no Node ID field */ + ogs_assert(tlv_node_id == NULL); + status = OGS_PFCP_STATUS_NODE_ID_NONE; + goto done; + + default: + status = OGS_PFCP_ERROR_UNKNOWN_MESSAGE; + goto done; + } + + memcpy(node_id, tlv_node_id->data, tlv_node_id->len); + + if (node_id->type != OGS_PFCP_NODE_ID_IPV4 && + node_id->type != OGS_PFCP_NODE_ID_IPV6 && + node_id->type != OGS_PFCP_NODE_ID_FQDN) { + ogs_error("Semantic incorrect message[%d] type[%d]", + message->h.type, node_id->type); + return OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE; + } + + /* Node ID is valid */ + status = OGS_PFCP_STATUS_SUCCESS; + +done: + return status; +} + +ogs_sockaddr_t *ogs_pfcp_node_id_to_addrinfo(const ogs_pfcp_node_id_t *node_id) +{ + ogs_sockaddr_t *p; + int ret; + uint16_t port = ogs_pfcp_self()->pfcp_port; + char fqdn[OGS_MAX_FQDN_LEN+1]; + + ogs_assert(node_id); + switch (node_id->type) { + + /*------------------------------------------------ + * 1) IPv4 + *-----------------------------------------------*/ + case OGS_PFCP_NODE_ID_IPV4: + p = (ogs_sockaddr_t *)ogs_calloc(1, sizeof(*p)); + if (!p) { + ogs_error("ogs_calloc() failed"); + return NULL; + } + p->sa.sa_family = AF_INET; + p->sin.sin_port = htobe16(port); + p->sin.sin_addr.s_addr = node_id->addr; + p->next = NULL; + return p; + + /*------------------------------------------------ + * 2) IPv6 + *-----------------------------------------------*/ + case OGS_PFCP_NODE_ID_IPV6: + p = (ogs_sockaddr_t *)ogs_calloc(1, sizeof(*p)); + if (!p) { + ogs_error("ogs_calloc() failed"); + return NULL; + } + p->sa.sa_family = AF_INET6; + p->sin6.sin6_port = htobe16(port); + /* Copy 16 bytes of IPv6 address */ + memcpy(&p->sin6.sin6_addr, node_id->addr6, 16); + p->next = NULL; + return p; + + /*------------------------------------------------ + * 3) FQDN + *-----------------------------------------------*/ + case OGS_PFCP_NODE_ID_FQDN: + /* If the FQDN is not empty, we attempt DNS resolution. + * ogs_addaddrinfo() is a placeholder for your actual + * DNS -> ogs_sockaddr_t function (often wraps getaddrinfo). + */ + /* Port=0 or set as needed, family=AF_UNSPEC, flags=0. */ + if (ogs_fqdn_parse(fqdn, node_id->fqdn, strlen(node_id->fqdn)) <= 0) { + ogs_error("ogs_fqdn_parse() error [%s]", node_id->fqdn); + return NULL; + } + ret = ogs_getaddrinfo(&p, AF_UNSPEC, fqdn, port, 0); + if (ret != 0) { + /* DNS resolution failed => *out remains NULL */ + ogs_error("ogs_addaddrinfo() failed"); + return NULL; + } + /* If FQDN is empty, just return with no addresses. */ + return p; + + /*------------------------------------------------ + * 4) Unsupported type or default + *-----------------------------------------------*/ + default: + /* Optionally handle an error or just return success + * with no addresses. + */ + ogs_error("Unknown type [%d]", node_id->type); + return NULL; + } +} + +/* Utility function to convert node_id to string for logging */ +const char *ogs_pfcp_node_id_to_string_static( + const ogs_pfcp_node_id_t *node_id) +{ + static char buffer[OGS_MAX_FQDN_LEN+1] = { 0, }; + + if (node_id) { + switch (node_id->type) { + case OGS_PFCP_NODE_ID_IPV4: + inet_ntop(AF_INET, &node_id->addr, buffer, sizeof(buffer)); + break; + case OGS_PFCP_NODE_ID_IPV6: + inet_ntop(AF_INET6, node_id->addr6, buffer, sizeof(buffer)); + break; + case OGS_PFCP_NODE_ID_FQDN: + if (ogs_fqdn_parse(buffer, + node_id->fqdn, + strlen(node_id->fqdn)) <= 0) + snprintf(buffer, sizeof(buffer), "%s", node_id->fqdn); + break; + default: + snprintf(buffer, sizeof(buffer), "Unknown"); + break; + } + } + + return buffer; +} diff --git a/lib/pfcp/util.h b/lib/pfcp/util.h new file mode 100644 index 000000000..ef6ae5d9a --- /dev/null +++ b/lib/pfcp/util.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2025 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#if !defined(OGS_PFCP_INSIDE) && !defined(OGS_PFCP_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_PFCP_UTIL_H +#define OGS_PFCP_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + /* Success with actual Node ID */ + OGS_PFCP_STATUS_SUCCESS = 0, + + /* Success with no Node ID (NONE type) */ + OGS_PFCP_STATUS_NODE_ID_NONE, + + /* Success with OPTIONAL node_id_tlv, but presence=0 */ + OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT, + + /* Error codes */ + OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE, + OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT, + OGS_PFCP_ERROR_NODE_ID_NOT_FOUND, + OGS_PFCP_ERROR_UNKNOWN_MESSAGE + +} ogs_pfcp_status_e; + +ogs_pfcp_status_e +ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message, + ogs_pfcp_node_id_t *node_id); + +ogs_sockaddr_t *ogs_pfcp_node_id_to_addrinfo(const ogs_pfcp_node_id_t *node_id); +const char *ogs_pfcp_node_id_to_string_static( + const ogs_pfcp_node_id_t *node_id); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_PFCP_UTIL_H */ diff --git a/lib/pfcp/xact.c b/lib/pfcp/xact.c index 30f3f9f12..fbbc2d97c 100644 --- a/lib/pfcp/xact.c +++ b/lib/pfcp/xact.c @@ -70,7 +70,6 @@ void ogs_pfcp_xact_final(void) ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data) { - char buf[OGS_ADDRSTRLEN]; ogs_pfcp_xact_t *xact = NULL; ogs_assert(node); @@ -109,11 +108,10 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, ogs_list_init(&xact->pdr_to_create_list); - ogs_debug("[%d] %s Create peer [%s]:%d", + ogs_debug("[%d] %s Create peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_sockaddr_to_string_static(node->addr_list)); return xact; } @@ -121,7 +119,6 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create( ogs_pfcp_node_t *node, uint32_t sqn) { - char buf[OGS_ADDRSTRLEN]; ogs_pfcp_xact_t *xact = NULL; ogs_assert(node); @@ -156,11 +153,10 @@ static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create( ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? &xact->node->local_list : &xact->node->remote_list, xact); - ogs_debug("[%d] %s Create peer [%s]:%d", + ogs_debug("[%d] %s Create peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_sockaddr_to_string_static(node->addr_list)); return xact; } @@ -183,7 +179,6 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_find_by_id(ogs_pool_id_t id) int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact, ogs_pfcp_header_t *hdesc, ogs_pkbuf_t *pkbuf) { - char buf[OGS_ADDRSTRLEN]; ogs_pfcp_xact_stage_t stage; ogs_pfcp_header_t *h = NULL; int pfcp_hlen = 0; @@ -193,12 +188,11 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact, ogs_assert(hdesc); ogs_assert(pkbuf); - ogs_debug("[%d] %s UPD TX-%d peer [%s]:%d", + ogs_debug("[%d] %s UPD TX-%d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", hdesc->type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); stage = ogs_pfcp_xact_get_stage(hdesc->type, xact->xid); if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) { @@ -290,15 +284,13 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact, static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type) { - char buf[OGS_ADDRSTRLEN]; ogs_pfcp_xact_stage_t stage; - ogs_debug("[%d] %s UPD RX-%d peer [%s]:%d", + ogs_debug("[%d] %s UPD RX-%d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); stage = ogs_pfcp_xact_get_stage(type, xact->xid); if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) { @@ -325,25 +317,23 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type) pfcp.t1_holding_duration); ogs_warn("[%d] %s Request Duplicated. Retransmit!" - " for step %d type %d peer [%s]:%d", + " for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, type, - OGS_ADDR(&xact->node->addr, - buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static( + xact->node->addr_list)); ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf)); } else { ogs_warn("[%d] %s Request Duplicated. Discard!" - " for step %d type %d peer [%s]:%d", + " for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, type, - OGS_ADDR(&xact->node->addr, - buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static( + xact->node->addr_list)); } return OGS_RETRY; @@ -391,25 +381,23 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type) pfcp.t1_holding_duration); ogs_warn("[%d] %s Request Duplicated. Retransmit!" - " for step %d type %d peer [%s]:%d", + " for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, type, - OGS_ADDR(&xact->node->addr, - buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static( + xact->node->addr_list)); ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf)); } else { ogs_warn("[%d] %s Request Duplicated. Discard!" - " for step %d type %d peer [%s]:%d", + " for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, type, - OGS_ADDR(&xact->node->addr, - buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static( + xact->node->addr_list)); } return OGS_RETRY; @@ -462,8 +450,6 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type) int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact) { - char buf[OGS_ADDRSTRLEN]; - uint8_t type; ogs_pkbuf_t *pkbuf = NULL; ogs_pfcp_xact_stage_t stage; @@ -471,11 +457,10 @@ int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact) ogs_assert(xact); ogs_assert(xact->node); - ogs_debug("[%d] %s Commit peer [%s]:%d", + ogs_debug("[%d] %s Commit peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); type = xact->seq[xact->step-1].type; stage = ogs_pfcp_xact_get_stage(type, xact->xid); @@ -581,7 +566,6 @@ void ogs_pfcp_xact_delayed_commit(ogs_pfcp_xact_t *xact, ogs_time_t duration) static void response_timeout(void *data) { - char buf[OGS_ADDRSTRLEN]; ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID; ogs_pfcp_xact_t *xact = NULL; @@ -597,12 +581,11 @@ static void response_timeout(void *data) ogs_assert(xact->node); ogs_debug("[%d] %s Response Timeout " - "for step %d type %d peer [%s]:%d", + "for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, xact->seq[xact->step-1].type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); if (--xact->response_rcount > 0) { ogs_pkbuf_t *pkbuf = NULL; @@ -617,12 +600,11 @@ static void response_timeout(void *data) ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf)); } else { ogs_warn("[%d] %s No Reponse. Give up! " - "for step %d type %d peer [%s]:%d", + "for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, xact->seq[xact->step-1].type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); if (xact->cb) xact->cb(xact, xact->data); @@ -633,7 +615,6 @@ static void response_timeout(void *data) static void holding_timeout(void *data) { - char buf[OGS_ADDRSTRLEN]; ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID; ogs_pfcp_xact_t *xact = NULL; @@ -649,12 +630,11 @@ static void holding_timeout(void *data) ogs_assert(xact->node); ogs_debug("[%d] %s Holding Timeout " - "for step %d type %d peer [%s]:%d", + "for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, xact->seq[xact->step-1].type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); if (--xact->holding_rcount > 0) { if (xact->tm_holding) @@ -662,19 +642,17 @@ static void holding_timeout(void *data) ogs_local_conf()->time.message.pfcp.t1_holding_duration); } else { ogs_debug("[%d] %s Delete Transaction " - "for step %d type %d peer [%s]:%d", + "for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, xact->seq[xact->step-1].type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); ogs_pfcp_xact_delete(xact); } } static void delayed_commit_timeout(void *data) { - char buf[OGS_ADDRSTRLEN]; ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID; ogs_pfcp_xact_t *xact = NULL; @@ -690,12 +668,11 @@ static void delayed_commit_timeout(void *data) ogs_assert(xact->node); ogs_debug("[%d] %s Delayed Send Timeout " - "for step %d type %d peer [%s]:%d", + "for step %d type %d peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", xact->step, xact->seq[xact->step-1].type, - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); ogs_pfcp_xact_commit(xact); } @@ -704,7 +681,6 @@ int ogs_pfcp_xact_receive( ogs_pfcp_node_t *node, ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact) { int rv; - char buf[OGS_ADDRSTRLEN]; uint8_t type; uint32_t sqn, xid; @@ -731,35 +707,33 @@ int ogs_pfcp_xact_receive( list = &node->local_list; break; default: - ogs_error("[%d] Unexpected type %u from PFCP peer [%s]:%d", - xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr)); + ogs_error("[%d] Unexpected type %u from PFCP peer %s", + xid, type, ogs_sockaddr_to_string_static(node->addr_list)); return OGS_ERROR; } ogs_assert(list); ogs_list_for_each(list, new) { if (new->xid == xid) { - ogs_debug("[%d] %s Find peer [%s]:%d", + ogs_debug("[%d] %s Find peer %s", new->xid, new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_sockaddr_to_string_static(node->addr_list)); break; } } if (!new) { - ogs_debug("[%d] Cannot find new type %u from PFCP peer [%s]:%d", - xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr)); + ogs_debug("[%d] Cannot find new type %u from PFCP peer %s", + xid, type, ogs_sockaddr_to_string_static(node->addr_list)); new = ogs_pfcp_xact_remote_create(node, sqn); } ogs_assert(new); - ogs_debug("[%d] %s Receive peer [%s]:%d", + ogs_debug("[%d] %s Receive peer %s", new->xid, new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_sockaddr_to_string_static(node->addr_list)); rv = ogs_pfcp_xact_update_rx(new, type); if (rv == OGS_ERROR) { @@ -811,16 +785,13 @@ static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(uint8_t type, uint32_t xid) int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact) { - char buf[OGS_ADDRSTRLEN]; - ogs_assert(xact); ogs_assert(xact->node); - ogs_debug("[%d] %s Delete peer [%s]:%d", + ogs_debug("[%d] %s Delete peer %s", xact->xid, xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE", - OGS_ADDR(&xact->node->addr, buf), - OGS_PORT(&xact->node->addr)); + ogs_sockaddr_to_string_static(xact->node->addr_list)); if (xact->seq[0].pkbuf) ogs_pkbuf_free(xact->seq[0].pkbuf); diff --git a/lib/sbi/client.c b/lib/sbi/client.c index e40255151..d9fef9bb9 100644 --- a/lib/sbi/client.c +++ b/lib/sbi/client.c @@ -129,6 +129,9 @@ ogs_sbi_client_t *ogs_sbi_client_add( ogs_strdup(ogs_sbi_self()->tls.client.private_key); if (ogs_sbi_self()->tls.client.cert) client->cert = ogs_strdup(ogs_sbi_self()->tls.client.cert); + if (ogs_sbi_self()->tls.client.sslkeylog) + client->sslkeylog = + ogs_strdup(ogs_sbi_self()->tls.client.sslkeylog); ogs_debug("ogs_sbi_client_add [%s]", OpenAPI_uri_scheme_ToString(scheme)); OGS_OBJECT_REF(client); @@ -212,6 +215,8 @@ void ogs_sbi_client_remove(ogs_sbi_client_t *client) ogs_free(client->private_key); if (client->cert) ogs_free(client->cert); + if (client->sslkeylog) + ogs_free(client->sslkeylog); if (client->fqdn) ogs_free(client->fqdn); @@ -369,6 +374,26 @@ static char *add_params_to_uri(CURL *easy, char *uri, ogs_hash_t *params) return uri; } +/* User-defined SSL_CTX callback function */ +static CURLcode sslctx_callback(CURL *curl, void *sslctx, void *userdata) +{ + SSL_CTX *ctx = (SSL_CTX *)sslctx; + ogs_sbi_client_t *client = userdata; + + ogs_assert(ctx); + ogs_assert(userdata); + + /* Ensure app data is set for SSL objects */ + SSL_CTX_set_app_data(ctx, client->sslkeylog); + +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + /* Set the SSL Key Log callback */ + SSL_CTX_set_keylog_callback(ctx, ogs_sbi_keylog_callback); +#endif + + return CURLE_OK; +} + static connection_t *connection_add( ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data) @@ -459,6 +484,7 @@ static connection_t *connection_add( curl_easy_setopt(conn->easy, CURLOPT_BUFFERSIZE, OGS_MAX_SDU_LEN); + /* HTTPS certificate-related settings */ if (client->scheme == OpenAPI_uri_scheme_https) { if (client->insecure_skip_verify) { curl_easy_setopt(conn->easy, CURLOPT_SSL_VERIFYPEER, 0); @@ -468,13 +494,23 @@ static connection_t *connection_add( curl_easy_setopt(conn->easy, CURLOPT_CAINFO, client->cacert); } + /* Set private key & certificate */ if (client->private_key && client->cert) { curl_easy_setopt(conn->easy, CURLOPT_SSLKEY, client->private_key); curl_easy_setopt(conn->easy, CURLOPT_SSLCERT, client->cert); } + + if (client->sslkeylog) { + /* Set SSL_CTX callback */ + curl_easy_setopt(conn->easy, CURLOPT_SSL_CTX_FUNCTION, + sslctx_callback); + + /* Optionally set additional user data */ + curl_easy_setopt(conn->easy, CURLOPT_SSL_CTX_DATA, client); + } } - /* HTTP Method */ + /* Configure HTTP Method */ if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 || strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PATCH) == 0 || strcmp(request->h.method, OGS_SBI_HTTP_METHOD_DELETE) == 0 || diff --git a/lib/sbi/client.h b/lib/sbi/client.h index d6687b38e..e9bfbc918 100644 --- a/lib/sbi/client.h +++ b/lib/sbi/client.h @@ -80,7 +80,7 @@ typedef struct ogs_sbi_client_s { OpenAPI_uri_scheme_e scheme; bool insecure_skip_verify; - char *cacert, *private_key, *cert; + char *cacert, *private_key, *cert, *sslkeylog; char *fqdn; uint16_t fqdn_port; diff --git a/lib/sbi/context.c b/lib/sbi/context.c index 55bda5a2c..f9740b5de 100644 --- a/lib/sbi/context.c +++ b/lib/sbi/context.c @@ -134,56 +134,73 @@ static int ogs_sbi_context_prepare(void) self.tls.server.scheme = OpenAPI_uri_scheme_http; self.tls.client.scheme = OpenAPI_uri_scheme_http; + /* Initialize delegated config with defaults */ + self.client_delegated_config.nrf.nfm = OGS_SBI_CLIENT_DELEGATED_AUTO; + self.client_delegated_config.nrf.disc = OGS_SBI_CLIENT_DELEGATED_AUTO; + self.client_delegated_config.scp.next = OGS_SBI_CLIENT_DELEGATED_AUTO; + return OGS_OK; } static int ogs_sbi_context_validation( const char *local, const char *nrf, const char *scp) { +#define MAX_MODE 3 + int i; + ogs_sbi_client_delegated_mode_e mode[MAX_MODE]; + + ogs_assert(context_initialized == 1); + /* If SMF is only used in 4G EPC, no SBI interface is required. */ if (local && strcmp(local, "smf") != 0 && ogs_sbi_server_first() == NULL) { ogs_error("No %s.sbi.address: in '%s'", local, ogs_app()->file); return OGS_ERROR; } - ogs_assert(context_initialized == 1); - switch (self.discovery_config.delegated) { - case OGS_SBI_DISCOVERY_DELEGATED_AUTO: - if (local && strcmp(local, "nrf") == 0) { - /* Skip NRF */ - } else if (local && strcmp(local, "scp") == 0) { - /* Skip SCP */ - } else if (local && strcmp(local, "smf") == 0) { - /* Skip SMF since SMF can run 4G */ - } else { - if (NF_INSTANCE_CLIENT(self.nrf_instance) || - NF_INSTANCE_CLIENT(self.scp_instance)) { + mode[0] = self.client_delegated_config.nrf.nfm; + mode[1] = self.client_delegated_config.nrf.disc; + mode[2] = self.client_delegated_config.scp.next; + + for (i = 0; i < MAX_MODE; i++) { + switch (mode[i]) { + case OGS_SBI_CLIENT_DELEGATED_AUTO: + if (local && strcmp(local, "nrf") == 0) { + /* Skip NRF */ + } else if (local && strcmp(local, "scp") == 0) { + /* Skip SCP */ + } else if (local && strcmp(local, "smf") == 0) { + /* Skip SMF since SMF can run 4G */ } else { - ogs_error("DELEGATED_AUTO - Both NRF and %s are unavailable", - scp && strcmp(scp, "next_scp") == 0 ? + if (NF_INSTANCE_CLIENT(self.nrf_instance) || + NF_INSTANCE_CLIENT(self.scp_instance)) { + } else { + ogs_error("[%d] DELEGATED_AUTO - " + "Both NRF and %s are unavailable", + i, scp && strcmp(scp, "next_scp") == 0 ? + "Next-hop SCP" : "SCP"); + return OGS_ERROR; + } + } + break; + case OGS_SBI_CLIENT_DELEGATED_YES: + if (NF_INSTANCE_CLIENT(self.scp_instance) == NULL) { + ogs_error("[%d] DELEGATED_YES - no %s available", + i, scp && strcmp(scp, "next_scp") == 0 ? "Next-hop SCP" : "SCP"); return OGS_ERROR; } + break; + case OGS_SBI_CLIENT_DELEGATED_NO: + if (NF_INSTANCE_CLIENT(self.nrf_instance) == NULL) { + ogs_error("[%d] DELEGATED_NO - no NRF available", i); + return OGS_ERROR; + } + break; + default: + ogs_fatal("[%d] Invalid dicovery-config delegated [%d]", + i, mode[i]); + ogs_assert_if_reached(); } - break; - case OGS_SBI_DISCOVERY_DELEGATED_YES: - if (NF_INSTANCE_CLIENT(self.scp_instance) == NULL) { - ogs_error("DELEGATED_YES - no %s available", - scp && strcmp(scp, "next_scp") == 0 ? - "Next-hop SCP" : "SCP"); - return OGS_ERROR; - } - break; - case OGS_SBI_DISCOVERY_DELEGATED_NO: - if (NF_INSTANCE_CLIENT(self.nrf_instance) == NULL) { - ogs_error("DELEGATED_NO - no NRF available"); - return OGS_ERROR; - } - break; - default: - ogs_fatal("Invalid dicovery-config delegated [%d]", - self.discovery_config.delegated); - ogs_assert_if_reached(); } if (ogs_sbi_self()->tls.server.scheme == OpenAPI_uri_scheme_https) { @@ -281,6 +298,11 @@ int ogs_sbi_context_parse_config( self.tls.server.cert = ogs_yaml_iter_value( &server_iter); + } else if (!strcmp(server_key, + "sslkeylogfile")) { + self.tls.server.sslkeylog = + ogs_yaml_iter_value( + &server_iter); } else if (!strcmp(server_key, "verify_client")) { self.tls.server.verify_client = @@ -340,6 +362,11 @@ int ogs_sbi_context_parse_config( self.tls.client.cert = ogs_yaml_iter_value( &client_iter); + } else if (!strcmp(client_key, + "client_sslkeylogfile")) { + self.tls.client.sslkeylog = + ogs_yaml_iter_value( + &client_iter); } } } @@ -481,6 +508,115 @@ int ogs_sbi_context_parse_config( } while (ogs_yaml_iter_type(&scp_array) == YAML_SEQUENCE_NODE); } + /* Parse delegated section */ + else if (!strcmp(client_key, "delegated")) { + ogs_yaml_iter_t delegated_iter; + ogs_yaml_iter_recurse(&client_iter, + &delegated_iter); + + while (ogs_yaml_iter_next( + &delegated_iter)) { + const char *del_key = + ogs_yaml_iter_key( + &delegated_iter); + if (!strcmp(del_key, "nrf")) { + ogs_yaml_iter_t nrf_iter; + ogs_yaml_iter_recurse( + &delegated_iter, &nrf_iter); + while (ogs_yaml_iter_next( + &nrf_iter)) { + const char *nrf_key = + ogs_yaml_iter_key( + &nrf_iter); + const char *nrf_val = + ogs_yaml_iter_value( + &nrf_iter); + ogs_assert(nrf_key); + + if (!strcmp(nrf_key,"nfm")) { + if (!strcmp(nrf_val,"no")) { + self.client_delegated_config.nrf.nfm = + OGS_SBI_CLIENT_DELEGATED_NO; + } else if (!strcmp( + nrf_val,"yes")) { + self.client_delegated_config.nrf.nfm = + OGS_SBI_CLIENT_DELEGATED_YES; + } else if (!strcmp( + nrf_val,"auto")) { + self.client_delegated_config.nrf.nfm = + OGS_SBI_CLIENT_DELEGATED_AUTO; + } else { + ogs_warn("unknown " + "'nfm' `%s`", + nrf_val); + } + } else if (!strcmp( + nrf_key,"disc")) { + if (!strcmp(nrf_val,"no")) { + self.client_delegated_config.nrf.disc = + OGS_SBI_CLIENT_DELEGATED_NO; + } else if (!strcmp( + nrf_val,"yes")) { + self.client_delegated_config.nrf.disc = + OGS_SBI_CLIENT_DELEGATED_YES; + } else if (!strcmp( + nrf_val,"auto")) { + self.client_delegated_config.nrf.disc = + OGS_SBI_CLIENT_DELEGATED_AUTO; + } else { + ogs_warn("unknown " + "'disc' `%s`", + nrf_val); + } + } else { + ogs_warn("unknown nrf " + "delegated key `%s`", + nrf_key); + } + } + } else if (!strcmp(del_key, "scp")) { + ogs_yaml_iter_t scp_iter; + ogs_yaml_iter_recurse( + &delegated_iter, &scp_iter); + while (ogs_yaml_iter_next( + &scp_iter)) { + const char *scp_key = + ogs_yaml_iter_key( + &scp_iter); + const char *scp_val = + ogs_yaml_iter_value( + &scp_iter); + ogs_assert(scp_key); + + if (!strcmp(scp_key,"next")) { + if (!strcmp(scp_val,"no")) { + self.client_delegated_config.scp.next = + OGS_SBI_CLIENT_DELEGATED_NO; + } else if (!strcmp( + scp_val,"yes")) { + self.client_delegated_config.scp.next = + OGS_SBI_CLIENT_DELEGATED_YES; + } else if (!strcmp( + scp_val,"auto")) { + self.client_delegated_config.scp.next = + OGS_SBI_CLIENT_DELEGATED_AUTO; + } else { + ogs_warn("unknown " + "'next' `%s`", + scp_val); + } + } else { + ogs_warn("unknown scp " + "delegated key `%s`", + scp_key); + } + } + } else { + ogs_warn("unknown delegated " + "key `%s`", del_key); + } + } + } } } else ogs_warn("unknown key `%s`", sbi_key); @@ -507,52 +643,6 @@ int ogs_sbi_context_parse_config( } while (ogs_yaml_iter_type( &service_name_iter) == YAML_SEQUENCE_NODE); - } else if (!strcmp(local_key, "discovery")) { - ogs_yaml_iter_t discovery_iter; - ogs_yaml_iter_recurse(&local_iter, &discovery_iter); - while (ogs_yaml_iter_next(&discovery_iter)) { - const char *discovery_key = - ogs_yaml_iter_key(&discovery_iter); - ogs_assert(discovery_key); - if (!strcmp(discovery_key, "delegated")) { - const char *delegated = - ogs_yaml_iter_value(&discovery_iter); - if (!strcmp(delegated, "auto")) - self.discovery_config.delegated = - OGS_SBI_DISCOVERY_DELEGATED_AUTO; - else if (!strcmp(delegated, "yes")) - self.discovery_config.delegated = - OGS_SBI_DISCOVERY_DELEGATED_YES; - else if (!strcmp(delegated, "no")) - self.discovery_config.delegated = - OGS_SBI_DISCOVERY_DELEGATED_NO; - else - ogs_warn("unknown 'delegated' value `%s`", - delegated); - } else if (!strcmp(discovery_key, "option")) { - ogs_yaml_iter_t option_iter; - ogs_yaml_iter_recurse( - &discovery_iter, &option_iter); - - while (ogs_yaml_iter_next(&option_iter)) { - const char *option_key = - ogs_yaml_iter_key(&option_iter); - ogs_assert(option_key); - - if (!strcmp(option_key, "no_service_names")) { - self.discovery_config.no_service_names = - ogs_yaml_iter_bool(&option_iter); - } else if (!strcmp(option_key, - "prefer_requester_nf_instance_id")) { - self.discovery_config. - prefer_requester_nf_instance_id = - ogs_yaml_iter_bool(&option_iter); - } else - ogs_warn("unknown key `%s`", option_key); - } - } else - ogs_warn("unknown key `%s`", discovery_key); - } } } } @@ -664,7 +754,7 @@ int ogs_sbi_context_parse_server_config( const char *dev = NULL; ogs_sockaddr_t *addr = NULL; - const char *private_key = NULL, *cert = NULL; + const char *private_key = NULL, *cert = NULL, *sslkeylog = NULL; bool verify_client = false; const char *verify_client_cacert = NULL; @@ -759,6 +849,8 @@ int ogs_sbi_context_parse_server_config( private_key = ogs_yaml_iter_value(&server_iter); } else if (!strcmp(server_key, "cert")) { cert = ogs_yaml_iter_value(&server_iter); + } else if (!strcmp(server_key, "sslkeylogfile")) { + sslkeylog = ogs_yaml_iter_value(&server_iter); } else if (!strcmp(server_key, "verify_client")) { verify_client = ogs_yaml_iter_bool(&server_iter); } else if (!strcmp(server_key, "verify_client_cacert")) { @@ -811,9 +903,38 @@ int ogs_sbi_context_parse_server_config( } addr = NULL; + /* ----- Process advertise (Host+Port Parsing Logic) ----- */ for (i = 0; i < num_of_advertise; i++) { - rv = ogs_addaddrinfo(&addr, family, advertise[i], port, 0); + uint16_t adv_port = port; /* Default to server's port */ + char *hostbuf = NULL; + const char *colon_pos = strchr(advertise[i], ':'); + + if (colon_pos) { + /* If a colon exists, split host and port */ + size_t host_len = colon_pos - advertise[i]; + + /* Allocate memory for the host part */ + hostbuf = (char *)ogs_malloc(host_len + 1); + ogs_assert(hostbuf); + + /* Copy the host part into hostbuf */ + memcpy(hostbuf, advertise[i], host_len); + hostbuf[host_len] = '\0'; + + /* Parse the port part */ + adv_port = (uint16_t)atoi(colon_pos + 1); + } else { + /* If no colon, treat the entire string as the host */ + hostbuf = ogs_strdup(advertise[i]); + ogs_assert(hostbuf); + } + + /* Add the parsed address info */ + rv = ogs_addaddrinfo(&addr, family, hostbuf, adv_port, 0); ogs_assert(rv == OGS_OK); + + /* Free the allocated memory */ + ogs_free(hostbuf); } node = ogs_list_first(&list); @@ -853,6 +974,12 @@ int ogs_sbi_context_parse_server_config( server->cert = ogs_strdup(cert); ogs_assert(server->cert); } + if (sslkeylog) { + if (server->sslkeylog) + ogs_free(server->sslkeylog); + server->sslkeylog = ogs_strdup(sslkeylog); + ogs_assert(server->sslkeylog); + } if (scheme == OpenAPI_uri_scheme_https) { if (!server->private_key) { @@ -902,6 +1029,12 @@ int ogs_sbi_context_parse_server_config( server->cert = ogs_strdup(cert); ogs_assert(server->cert); } + if (sslkeylog) { + if (server->sslkeylog) + ogs_free(server->sslkeylog); + server->sslkeylog = ogs_strdup(sslkeylog); + ogs_assert(server->sslkeylog); + } if (scheme == OpenAPI_uri_scheme_https) { if (!server->private_key) { @@ -939,6 +1072,7 @@ ogs_sbi_client_t *ogs_sbi_context_parse_client_config(ogs_yaml_iter_t *iter) const char *client_private_key = NULL; const char *client_cert = NULL; + const char *client_sslkeylog = NULL; bool rc; @@ -980,6 +1114,8 @@ ogs_sbi_client_t *ogs_sbi_context_parse_client_config(ogs_yaml_iter_t *iter) client_private_key = ogs_yaml_iter_value(iter); } else if (!strcmp(key, "client_cert")) { client_cert = ogs_yaml_iter_value(iter); + } else if (!strcmp(key, "client_sslkeylogfile")) { + client_sslkeylog = ogs_yaml_iter_value(iter); } } @@ -1049,6 +1185,13 @@ ogs_sbi_client_t *ogs_sbi_context_parse_client_config(ogs_yaml_iter_t *iter) ogs_assert(client->cert); } + if (client_sslkeylog) { + if (client->sslkeylog) + ogs_free(client->sslkeylog); + client->sslkeylog = ogs_strdup(client_sslkeylog); + ogs_assert(client->sslkeylog); + } + if ((!client_private_key && client_cert) || (client_private_key && !client_cert)) { ogs_error("Either the private key or certificate is missing."); @@ -1721,11 +1864,8 @@ void ogs_sbi_nf_instance_build_default(ogs_sbi_nf_instance_t *nf_instance) ogs_assert(advertise); /* First FQDN is selected */ - if (!hostname) { + if (!hostname) hostname = ogs_gethostname(advertise); - if (hostname) - continue; - } if (nf_instance->num_of_ipv4 < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) { ogs_sockaddr_t *addr = NULL; @@ -1795,11 +1935,8 @@ ogs_sbi_nf_service_t *ogs_sbi_nf_service_build_default( ogs_assert(advertise); /* First FQDN is selected */ - if (!hostname) { + if (!hostname) hostname = ogs_gethostname(advertise); - if (hostname) - continue; - } if (nf_service->num_of_addr < OGS_SBI_MAX_NUM_OF_IP_ADDRESS) { bool is_port = true; @@ -1912,6 +2049,7 @@ static void nf_service_associate_client(ogs_sbi_nf_service_t *nf_service) { ogs_sbi_client_t *client = NULL; ogs_sockaddr_t *addr = NULL, *addr6 = NULL; + uint16_t port = 0; ogs_assert(nf_service->scheme); @@ -1919,15 +2057,28 @@ static void nf_service_associate_client(ogs_sbi_nf_service_t *nf_service) if (nf_service->num_of_addr) { addr = nf_service->addr[0].ipv4; addr6 = nf_service->addr[0].ipv6; + + /* + * Added support for using custom port numbers with FQDN. + * + * This code checks if a user-defined port number is provided in the + * NFService structure. If the is_port flag is set, the port is + * assigned the specified value. + * + * This ensures that services using non-default ports can be accessed + * correctly, regardless of whether TLS is enabled or not. + */ + if (nf_service->addr[0].is_port) + port = nf_service->addr[0].port; } if (nf_service->fqdn || addr || addr6) { client = ogs_sbi_client_find( - nf_service->scheme, nf_service->fqdn, 0, addr, addr6); + nf_service->scheme, nf_service->fqdn, port, addr, addr6); if (!client) { ogs_debug("%s: ogs_sbi_client_add()", OGS_FUNC); client = ogs_sbi_client_add( - nf_service->scheme, nf_service->fqdn, 0, addr, addr6); + nf_service->scheme, nf_service->fqdn, port, addr, addr6); if (!client) { ogs_error("%s: ogs_sbi_client_add() failed", OGS_FUNC); return; @@ -2539,6 +2690,9 @@ void ogs_sbi_subscription_data_remove( if (subscription_data->subscr_cond.service_name) ogs_free(subscription_data->subscr_cond.service_name); + + if (subscription_data->subscr_cond.nf_instance_id) + ogs_free(subscription_data->subscr_cond.nf_instance_id); if (subscription_data->t_validity) ogs_timer_delete(subscription_data->t_validity); @@ -2691,3 +2845,29 @@ bool ogs_sbi_fqdn_in_vplmn(char *fqdn) return false; } + +/* OpenSSL Key Log Callback */ +void ogs_sbi_keylog_callback(const SSL *ssl, const char *line) +{ + SSL_CTX *ctx = NULL; + FILE *file = NULL; + const char *sslkeylog_file = NULL; + + ogs_assert(ssl); + ogs_assert(line); + + /* Retrieve SSL_CTX from SSL object */ + ctx = SSL_get_SSL_CTX(ssl); + ogs_assert(ctx); + + sslkeylog_file = (const char *)SSL_CTX_get_app_data(ctx); + ogs_assert(sslkeylog_file); + + file = fopen(sslkeylog_file, "a"); + if (file) { + fprintf(file, "%s\n", line); + fclose(file); + } else { + ogs_error("Failed to open SSL key log file: %s", sslkeylog_file); + } +} diff --git a/lib/sbi/context.h b/lib/sbi/context.h index 326fa46b7..6d156adfd 100644 --- a/lib/sbi/context.h +++ b/lib/sbi/context.h @@ -36,19 +36,25 @@ typedef struct ogs_sbi_smf_info_s ogs_sbi_smf_info_t; typedef struct ogs_sbi_nf_instance_s ogs_sbi_nf_instance_t; typedef enum { - OGS_SBI_DISCOVERY_DELEGATED_AUTO = 0, - OGS_SBI_DISCOVERY_DELEGATED_YES, - OGS_SBI_DISCOVERY_DELEGATED_NO, -} ogs_sbi_discovery_delegated_mode; + OGS_SBI_CLIENT_DELEGATED_AUTO = 0, + OGS_SBI_CLIENT_DELEGATED_YES, + OGS_SBI_CLIENT_DELEGATED_NO, +} ogs_sbi_client_delegated_mode_e; -typedef struct ogs_sbi_discovery_config_s { - ogs_sbi_discovery_delegated_mode delegated; - bool no_service_names; - bool prefer_requester_nf_instance_id; -} ogs_sbi_discovery_config_t; +/* To hold all delegated config under sbi.client.delegated */ +typedef struct ogs_sbi_client_delegated_config_s { + struct { + ogs_sbi_client_delegated_mode_e nfm; /* e.g. Registration, Heartbeat */ + ogs_sbi_client_delegated_mode_e disc; /* NF discovery */ + } nrf; + struct { + ogs_sbi_client_delegated_mode_e next; /* Next-hop SCP delegation */ + } scp; +} ogs_sbi_client_delegated_config_t; typedef struct ogs_sbi_context_s { - ogs_sbi_discovery_config_t discovery_config; /* SCP Discovery Delegated */ + /* For sbi.client.delegated */ + ogs_sbi_client_delegated_config_t client_delegated_config; #define OGS_HOME_NETWORK_PKI_VALUE_MIN 1 #define OGS_HOME_NETWORK_PKI_VALUE_MAX 254 @@ -65,6 +71,7 @@ typedef struct ogs_sbi_context_s { const char *private_key; const char *cert; + const char *sslkeylog; bool verify_client; const char *verify_client_cacert; @@ -77,6 +84,7 @@ typedef struct ogs_sbi_context_s { const char *private_key; const char *cert; + const char *sslkeylog; } client; } tls; @@ -300,6 +308,7 @@ typedef struct ogs_sbi_subscription_data_s { struct { OpenAPI_nf_type_e nf_type; /* nfType */ char *service_name; /* ServiceName */ + char *nf_instance_id; /* NF Instance Id */ } subscr_cond; uint64_t requester_features; @@ -573,6 +582,8 @@ bool ogs_sbi_supi_in_vplmn(char *supi); bool ogs_sbi_plmn_id_in_vplmn(ogs_plmn_id_t *plmn_id); bool ogs_sbi_fqdn_in_vplmn(char *fqdn); +void ogs_sbi_keylog_callback(const SSL *ssl, const char *line); + #ifdef __cplusplus } #endif diff --git a/lib/sbi/conv.c b/lib/sbi/conv.c index 0950f2d8f..5c51ee530 100644 --- a/lib/sbi/conv.c +++ b/lib/sbi/conv.c @@ -103,7 +103,7 @@ char *ogs_supi_from_suci(char *suci) p = tmp; i = 0; - while((array[i++] = strsep(&p, "-"))) { + while((i < MAX_SUCI_TOKEN) && (array[i++] = strsep(&p, "-"))) { /* Empty Body */ } @@ -728,12 +728,12 @@ char *ogs_sbi_bitrate_to_string(uint64_t bitrate, int unit) uint64_t ogs_sbi_bitrate_from_string(char *str) { char *unit = NULL; - uint64_t bitrate = 0; + double bitrate = 0; ogs_assert(str); uint64_t mul = 1; unit = strrchr(str, ' '); - bitrate = atoll(str); + bitrate = atof(str); if (!unit) { ogs_error("No Unit [%s]", str); @@ -761,7 +761,7 @@ uint64_t ogs_sbi_bitrate_from_string(char *str) else bitrate *= mul; - return bitrate; + return (uint64_t) bitrate; } #define MAX_TIMESTR_LEN 128 @@ -1211,6 +1211,35 @@ void ogs_sbi_free_plmn_list(OpenAPI_list_t *PlmnList) OpenAPI_list_free(PlmnList); } +/** + * Compares an ogs_plmn_id_t structure with an OpenAPI_plmn_id_t structure. + * + * @param plmn_list The PLMN-ID in ogs_plmn_id_t format. + * @param PlmnList The PLMN-ID in OpenAPI_plmn_id_t format. + * @return true if the PLMN-IDs are equal; otherwise, false. + */ +bool ogs_sbi_compare_plmn_list( + ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId) +{ + ogs_plmn_id_t temp_plmn_id; + + ogs_assert(plmn_id); + ogs_assert(PlmnId); + ogs_assert(PlmnId->mcc); + ogs_assert(PlmnId->mnc); + + /* Convert OpenAPI_plmn_id_t to ogs_plmn_id_t */ + ogs_sbi_parse_plmn_id(&temp_plmn_id, PlmnId); + + /* Compare MCC and MNC values */ + if (ogs_plmn_id_mcc(plmn_id) == ogs_plmn_id_mcc(&temp_plmn_id) && + ogs_plmn_id_mnc(plmn_id) == ogs_plmn_id_mnc(&temp_plmn_id)) { + return true; + } + + return false; +} + OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id) { OpenAPI_plmn_id_nid_t *PlmnIdNid = NULL; diff --git a/lib/sbi/conv.h b/lib/sbi/conv.h index dc01e3069..6a7d055f7 100644 --- a/lib/sbi/conv.h +++ b/lib/sbi/conv.h @@ -98,6 +98,8 @@ OpenAPI_list_t *ogs_sbi_build_plmn_list( int ogs_sbi_parse_plmn_list( ogs_plmn_id_t *plmn_list, OpenAPI_list_t *PlmnList); void ogs_sbi_free_plmn_list(OpenAPI_list_t *PlmnList); +bool ogs_sbi_compare_plmn_list( + ogs_plmn_id_t *plmn_id, OpenAPI_plmn_id_t *PlmnId); OpenAPI_plmn_id_nid_t *ogs_sbi_build_plmn_id_nid(ogs_plmn_id_t *plmn_id); bool ogs_sbi_parse_plmn_id_nid( diff --git a/lib/sbi/message.c b/lib/sbi/message.c index 4596004d3..9c591b57a 100644 --- a/lib/sbi/message.c +++ b/lib/sbi/message.c @@ -434,8 +434,7 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message) &discovery_option->guami.amf_id)); } } - if (ogs_sbi_self()->discovery_config.no_service_names == false && - discovery_option->num_of_service_names) { + if (discovery_option->num_of_service_names) { /* * Issues #1730 diff --git a/lib/sbi/message.h b/lib/sbi/message.h index 7fbad0c03..9e328337f 100644 --- a/lib/sbi/message.h +++ b/lib/sbi/message.h @@ -153,6 +153,7 @@ extern "C" { #define OGS_SBI_PATCH_PATH_NF_STATUS "/nfStatus" #define OGS_SBI_PATCH_PATH_LOAD "/load" +#define OGS_SBI_PATCH_PATH_PLMN_LIST "/plmnList" #define OGS_SBI_PATCH_PATH_VALIDITY_TIME "/validityTime" diff --git a/lib/sbi/nghttp2-server.c b/lib/sbi/nghttp2-server.c index de8cc2a1c..9fcbd108d 100644 --- a/lib/sbi/nghttp2-server.c +++ b/lib/sbi/nghttp2-server.c @@ -196,7 +196,9 @@ static int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) #endif /* OPENSSL_VERSION_NUMBER >= 0x1010000fL */ } -static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) +static SSL_CTX *create_ssl_ctx( + const char *key_file, const char *cert_file, + const char *sslkeylog_file) { SSL_CTX *ssl_ctx; uint64_t ssl_opts; @@ -210,6 +212,16 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) return NULL; } + /* Set key log files for each SSL_CTX */ + if (sslkeylog_file) { + /* Ensure app data is set for SSL objects */ + SSL_CTX_set_app_data(ssl_ctx, sslkeylog_file); +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + /* Set the SSL Key Log callback */ + SSL_CTX_set_keylog_callback(ssl_ctx, ogs_sbi_keylog_callback); +#endif + } + ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | @@ -322,7 +334,8 @@ static int server_start(ogs_sbi_server_t *server, /* Create SSL CTX */ if (server->scheme == OpenAPI_uri_scheme_https) { - server->ssl_ctx = create_ssl_ctx(server->private_key, server->cert); + server->ssl_ctx = create_ssl_ctx( + server->private_key, server->cert, server->sslkeylog); if (!server->ssl_ctx) { ogs_error("Cannot create SSL CTX"); return OGS_ERROR; diff --git a/lib/sbi/nnrf-build.c b/lib/sbi/nnrf-build.c index 71c3d2d09..84bf5c33b 100644 --- a/lib/sbi/nnrf-build.c +++ b/lib/sbi/nnrf-build.c @@ -61,6 +61,28 @@ ogs_sbi_request_t *ogs_nnrf_nfm_build_register(void) goto end; } + /* + * TS29510 + * 6.1.6.2 Structured data types + * 6.1.6.2.2 Type: NFProfile + * Table 6.1.6.2.2-1: Definition of type NFProfile + * + * NF Profile Changes Support Indicator. + * See Annex B. + * + * This IE may be present in the NFRegister or + * NFUpdate (NF Profile Complete Replacement) + * request and shall be absent in the response. + * + * true: the NF Service Consumer supports receiving + * NF Profile Changes in the response. + * + * false (default): the NF Service Consumer does not + * support receiving NF Profile Changes in the response. + */ + NFProfile->is_nf_profile_changes_support_ind = true; + NFProfile->nf_profile_changes_support_ind = true; + message.NFProfile = NFProfile; request = ogs_sbi_build_request(&message); @@ -146,9 +168,6 @@ OpenAPI_nf_profile_t *ogs_nnrf_nfm_build_nf_profile( OpenAPI_list_free(PlmnIdList); } - NFProfile->is_nf_profile_changes_support_ind = true; - NFProfile->nf_profile_changes_support_ind = true; - if (nf_instance->fqdn) NFProfile->fqdn = ogs_strdup(nf_instance->fqdn); diff --git a/lib/sbi/nnrf-path.c b/lib/sbi/nnrf-path.c index 957f633e2..3ecf5ba7e 100644 --- a/lib/sbi/nnrf-path.c +++ b/lib/sbi/nnrf-path.c @@ -32,8 +32,9 @@ bool ogs_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, nf_instance); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, nf_instance); ogs_expect(rc == true); ogs_sbi_request_free(request); @@ -54,8 +55,9 @@ bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance) return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, nf_instance); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, nf_instance); ogs_expect(rc == true); ogs_sbi_request_free(request); @@ -76,8 +78,9 @@ bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance) return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, nf_instance); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, nf_instance); ogs_expect(rc == true); ogs_sbi_request_free(request); @@ -120,8 +123,9 @@ bool ogs_nnrf_nfm_send_nf_status_subscribe( return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, subscription_data); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, subscription_data); ogs_expect(rc == true); ogs_sbi_request_free(request); @@ -143,8 +147,9 @@ bool ogs_nnrf_nfm_send_nf_status_update( return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, subscription_data); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, subscription_data); ogs_expect(rc == true); ogs_sbi_request_free(request); @@ -166,8 +171,9 @@ bool ogs_nnrf_nfm_send_nf_status_unsubscribe( return false; } - rc = ogs_sbi_send_notification_request( - OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, request, subscription_data); + rc = ogs_sbi_send_request_to_nrf( + OGS_SBI_SERVICE_TYPE_NNRF_NFM, NULL, + ogs_sbi_client_handler, request, subscription_data); ogs_expect(rc == true); ogs_sbi_request_free(request); diff --git a/lib/sbi/path.c b/lib/sbi/path.c index 0180c450c..4c8c50e67 100644 --- a/lib/sbi/path.c +++ b/lib/sbi/path.c @@ -273,11 +273,11 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact) discovery_option = xact->discovery_option; /* SCP Availability */ - if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_AUTO) { + if (ogs_sbi_self()->client_delegated_config.nrf.disc == + OGS_SBI_CLIENT_DELEGATED_AUTO) { scp_client = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); - } else if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_YES) { + } else if (ogs_sbi_self()->client_delegated_config.nrf.disc == + OGS_SBI_CLIENT_DELEGATED_YES) { scp_client = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); ogs_assert(scp_client); } @@ -794,63 +794,88 @@ bool ogs_sbi_send_request_to_client( return rc; } -bool ogs_sbi_send_notification_request( - ogs_sbi_service_type_e service_type, +bool ogs_sbi_send_request_to_nrf( + ogs_sbi_service_type_e nrf_service_type, ogs_sbi_discovery_option_t *discovery_option, + ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data) { bool rc; - ogs_sbi_client_t *client = NULL, *scp_client = NULL; - OpenAPI_nf_type_e target_nf_type = OpenAPI_nf_type_NULL; + ogs_sbi_client_t *nrf_client = NULL, *scp_client = NULL; + ogs_sbi_client_delegated_mode_e mode = OGS_SBI_CLIENT_DELEGATED_AUTO; - ogs_assert(service_type); - target_nf_type = ogs_sbi_service_type_to_nf_type(service_type); - ogs_assert(target_nf_type); + ogs_assert(nrf_service_type); ogs_assert(request); scp_client = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); - if (target_nf_type == OpenAPI_nf_type_NRF) - client = NF_INSTANCE_CLIENT(ogs_sbi_self()->nrf_instance); - else { - ogs_fatal("Not implemented[%s]", - ogs_sbi_service_type_to_name(service_type)); - ogs_assert_if_reached(); - } + nrf_client = NF_INSTANCE_CLIENT(ogs_sbi_self()->nrf_instance); - if (scp_client) { - /************************* - * INDIRECT COMMUNICATION - *************************/ - build_default_discovery_parameter( - request, service_type, discovery_option); + /* Decide which delegated mode to use */ + if (nrf_service_type == OGS_SBI_SERVICE_TYPE_NNRF_NFM) + mode = ogs_sbi_self()->client_delegated_config.nrf.nfm; + else if (nrf_service_type == OGS_SBI_SERVICE_TYPE_NNRF_DISC) + mode = ogs_sbi_self()->client_delegated_config.nrf.disc; + /* else if it's some other Nnrf service, fallback to AUTO or keep default */ - rc = ogs_sbi_client_send_via_scp_or_sepp( - scp_client, ogs_sbi_client_handler, request, data); - ogs_expect(rc == true); - - } else if (client) { - - /*********************** - * DIRECT COMMUNICATION - ***********************/ - - /* NRF is available */ - rc = ogs_sbi_client_send_request( - client, ogs_sbi_client_handler, request, data); - ogs_expect(rc == true); - - - } else { - ogs_fatal("[%s:%s] Cannot send request [%s:%s:%s]", - client ? "CLIENT" : "No-CLIENT", - scp_client ? "SCP" : "No-SCP", - ogs_sbi_service_type_to_name(service_type), + switch (mode) { + case OGS_SBI_CLIENT_DELEGATED_NO: + /* NO => Direct communication (NRF must exist) */ + if (!nrf_client) { + ogs_fatal("[No-NRF] Cannot send request [%s:%s:%s]", + ogs_sbi_service_type_to_name(nrf_service_type), request->h.service.name, request->h.api.version); - rc = false; - ogs_assert_if_reached(); + ogs_assert_if_reached(); + return false; + } + /* Send directly to NRF */ + rc = ogs_sbi_client_send_request(nrf_client, client_cb, + request, data); + ogs_expect(rc == true); + break; + + case OGS_SBI_CLIENT_DELEGATED_YES: + /* YES => Indirect communication (SCP must exist) */ + if (!scp_client) { + ogs_fatal("[No-SCP] Cannot send request [%s:%s:%s]", + ogs_sbi_service_type_to_name(nrf_service_type), + request->h.service.name, request->h.api.version); + ogs_assert_if_reached(); + return false; + } + /* Indirect via SCP, build discovery parameter if needed */ + build_default_discovery_parameter(request, nrf_service_type, + discovery_option); + rc = ogs_sbi_client_send_via_scp_or_sepp(scp_client, client_cb, + request, data); + ogs_expect(rc == true); + break; + + case OGS_SBI_CLIENT_DELEGATED_AUTO: + default: + /* + * AUTO => If SCP is present, use it; otherwise direct. + */ + if (scp_client) { + build_default_discovery_parameter(request, nrf_service_type, + discovery_option); + rc = ogs_sbi_client_send_via_scp_or_sepp(scp_client, client_cb, + request, data); + ogs_expect(rc == true); + } else if (nrf_client) { + rc = ogs_sbi_client_send_request(nrf_client, client_cb, + request, data); + ogs_expect(rc == true); + } else { + ogs_fatal("[No-NRF:No-SCP] Cannot send request [%s:%s:%s]", + ogs_sbi_service_type_to_name(nrf_service_type), + request->h.service.name, request->h.api.version); + ogs_assert_if_reached(); + return false; + } + break; } - return true; + return rc; } bool ogs_sbi_send_response(ogs_sbi_stream_t *stream, int status) @@ -1024,9 +1049,7 @@ static void build_default_discovery_parameter( OGS_SBI_CUSTOM_DISCOVERY_REQUESTER_NF_INSTANCE_ID, discovery_option->requester_nf_instance_id); } - if (ogs_sbi_self()->discovery_config. - no_service_names == false && - discovery_option->num_of_service_names) { + if (discovery_option->num_of_service_names) { bool rc = false; /* send array items separated by a comma */ diff --git a/lib/sbi/path.h b/lib/sbi/path.h index 3aba3f11c..908bd5c11 100644 --- a/lib/sbi/path.h +++ b/lib/sbi/path.h @@ -40,9 +40,10 @@ bool ogs_sbi_send_request_with_sepp_discovery( bool ogs_sbi_send_request_to_client( ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data); -bool ogs_sbi_send_notification_request( - ogs_sbi_service_type_e service_type, +bool ogs_sbi_send_request_to_nrf( + ogs_sbi_service_type_e nrf_service_type, ogs_sbi_discovery_option_t *discovery_option, + ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data); #define ogs_sbi_send_http_status_no_content(__sTREAM) \ diff --git a/lib/sbi/server.c b/lib/sbi/server.c index f0c1e207e..e0bc83e8c 100644 --- a/lib/sbi/server.c +++ b/lib/sbi/server.c @@ -75,6 +75,8 @@ ogs_sbi_server_t *ogs_sbi_server_add( ogs_strdup(ogs_sbi_self()->tls.server.private_key); if (ogs_sbi_self()->tls.server.cert) server->cert = ogs_strdup(ogs_sbi_self()->tls.server.cert); + if (ogs_sbi_self()->tls.server.sslkeylog) + server->sslkeylog = ogs_strdup(ogs_sbi_self()->tls.server.sslkeylog); server->verify_client = ogs_sbi_self()->tls.server.verify_client; if (ogs_sbi_self()->tls.server.verify_client_cacert) @@ -112,6 +114,8 @@ void ogs_sbi_server_remove(ogs_sbi_server_t *server) ogs_free(server->private_key); if (server->cert) ogs_free(server->cert); + if (server->sslkeylog) + ogs_free(server->sslkeylog); ogs_pool_id_free(&server_pool, server); } diff --git a/lib/sbi/server.h b/lib/sbi/server.h index af58a0cf1..19db7d806 100644 --- a/lib/sbi/server.h +++ b/lib/sbi/server.h @@ -41,7 +41,7 @@ typedef struct ogs_sbi_server_s { char *interface; OpenAPI_uri_scheme_e scheme; - char *private_key, *cert; + char *private_key, *cert, *sslkeylog; bool verify_client; char *verify_client_cacert; diff --git a/lib/sctp/ogs-lksctp.c b/lib/sctp/ogs-lksctp.c index 89a6b985c..c40a99136 100644 --- a/lib/sctp/ogs-lksctp.c +++ b/lib/sctp/ogs-lksctp.c @@ -53,138 +53,367 @@ ogs_sock_t *ogs_sctp_socket(int family, int type) return new; } -ogs_sock_t *ogs_sctp_server( - int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) +/** + * Determines the appropriate SCTP socket family based on the provided + * address list. + * Returns AF_INET6 if any address in sa_list is IPv6, otherwise AF_INET. + * Returns AF_UNSPEC if sa_list is NULL or no suitable family is found. + * + * @param sa_list List of addresses to check. + * @return AF_INET6, AF_INET, or AF_UNSPEC if no suitable family is found. + */ +static int sctp_socket_family_from_addr_list(const ogs_sockaddr_t *sa_list) { - int rv; - char buf[OGS_ADDRSTRLEN]; + const ogs_sockaddr_t *addr = sa_list; - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; - ogs_sockopt_t option; + if (!sa_list) { + ogs_error("Address list is NULL"); + return AF_UNSPEC; + } - ogs_assert(sa_list); - - ogs_sockopt_init(&option); - if (socket_option) - memcpy(&option, socket_option, sizeof option); - - addr = sa_list; - while (addr) { - new = ogs_sctp_socket(addr->ogs_sa_family, type); - if (new) { - rv = ogs_sctp_peer_addr_params(new, &option); - ogs_assert(rv == OGS_OK); - - rv = ogs_sctp_rto_info(new, &option); - ogs_assert(rv == OGS_OK); - - rv = ogs_sctp_initmsg(new, &option); - ogs_assert(rv == OGS_OK); - - if (option.sctp_nodelay == true) { - rv = ogs_sctp_nodelay(new, true); - ogs_assert(rv == OGS_OK); - } else - ogs_warn("SCTP NO_DELAY Disabled"); - - if (option.so_linger.l_onoff == true) { - rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); - ogs_assert(rv == OGS_OK); - } - - rv = ogs_listen_reusable(new->fd, true); - ogs_assert(rv == OGS_OK); - - if (ogs_sock_bind(new, addr) == OGS_OK) { - ogs_debug("sctp_server() [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); - break; - } - - ogs_sock_destroy(new); + /* Iterate through the address list to find an IPv6 address */ + while (addr != NULL) { + if (addr->ogs_sa_family == AF_INET6) { + return AF_INET6; } - addr = addr->next; } - if (addr == NULL) { - ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "sctp_server() [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + /* Default to AF_INET if no IPv6 address is found */ + return AF_INET; +} + + +/** + * @brief + * 1) Count the number of addresses in sa_list and determine the total + * buffer size. + * 2) Allocate a single continuous buffer (unsigned char). + * 3) Copy each address (sockaddr_in or sockaddr_in6) into this continuous + * buffer. + * + * @param sa_list Linked list of ogs_sockaddr_t structures. + * @param out_count [OUT] Receives the number of addresses. + * @param out_total_len [OUT] Receives the total bytes for the continuous + * buffer. + * + * @return + * On success, returns a pointer to the allocated buffer containing all + * addresses. On failure, logs an error and returns NULL. + */ +static unsigned char *create_continuous_address_buffer( + ogs_sockaddr_t *sa_list, + int *out_count, + int *out_total_len) +{ + ogs_sockaddr_t *addr; + int addr_count = 0; + int total_len = 0; + unsigned char *addr_buf = NULL; + int offset = 0; + + /* 1) Count addresses and total buffer size needed. */ + for (addr = sa_list; addr; addr = addr->next) { + addr_count++; + /* E.g., sizeof(sockaddr_in) or sizeof(sockaddr_in6). */ + total_len += ogs_sockaddr_len(addr); + } + + if (addr_count == 0) { + ogs_error("No valid address in sa_list"); return NULL; } - ogs_assert(new); + /* 2) Allocate the continuous buffer (unsigned char). */ + addr_buf = ogs_calloc(1, total_len); + if (!addr_buf) { + ogs_error("Failed to allocate memory for addr_buf"); + return NULL; + } - rv = ogs_sock_listen(new); + /* 3) Copy each address structure into addr_buf. */ + offset = 0; + for (addr = sa_list; addr; addr = addr->next) { + socklen_t socklen = ogs_sockaddr_len(addr); + memcpy(addr_buf + offset, &addr->sa, socklen); + offset += socklen; + } + + /* Pass back the number of addresses and total length. */ + *out_count = addr_count; + *out_total_len = total_len; + + return addr_buf; +} + +/** + * @brief Create an SCTP server socket and bind multiple addresses at once + * using sctp_bindx(). + * + * @param type SCTP socket type (e.g., SOCK_SEQPACKET or SOCK_STREAM) + * @param sa_list Linked list of ogs_sockaddr_t structures + * @param socket_option Additional socket/SCTP options + * + * @return + * On success, returns a pointer to an ogs_sock_t instance; on failure, + * returns NULL. + */ +ogs_sock_t *ogs_sctp_server( + int type, + ogs_sockaddr_t *sa_list, + ogs_sockopt_t *socket_option) +{ + int rv; + int sa_family; + ogs_sock_t *new_sock = NULL; + ogs_sockopt_t option; + + /* Variables for sctp_bindx() usage. */ + unsigned char *addr_buf = NULL; + int addr_count = 0; + int total_len = 0; + + ogs_assert(sa_list); + + /* Initialize socket options. */ + ogs_sockopt_init(&option); + if (socket_option) + memcpy(&option, socket_option, sizeof(option)); + + /* + * Obtain a contiguous buffer for all addresses: + * 1) Count the addresses. + * 2) Allocate the buffer. + * 3) Copy the addresses into the buffer. + */ + addr_buf = create_continuous_address_buffer( + sa_list, &addr_count, &total_len); + if (!addr_buf) { + /* The helper logs errors, so just return. */ + ogs_error("create_continuous_address_buffer() failed"); + goto err; + } + + /* Determine the appropriate address family from sa_list */ + sa_family = sctp_socket_family_from_addr_list(sa_list); + if (sa_family == AF_UNSPEC) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_client() No suitable address family found " + "in sa_list"); + goto err; + } + + /* Create the SCTP socket using the determined address family */ + new_sock = ogs_sctp_socket(sa_family, type); + + /* Configure SCTP-specific options. */ + rv = ogs_sctp_peer_addr_params(new_sock, &option); ogs_assert(rv == OGS_OK); - return new; + rv = ogs_sctp_rto_info(new_sock, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new_sock, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new_sock, true); + ogs_assert(rv == OGS_OK); + } else { + ogs_warn("SCTP NO_DELAY Disabled"); + } + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new_sock, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + /* Enable address reuse if needed. */ + rv = ogs_listen_reusable(new_sock->fd, true); + ogs_assert(rv == OGS_OK); + + /* + * Bind all addresses at once using sctp_bindx(). + * (struct sockaddr *)addr_buf points to the contiguous buffer. + */ + rv = sctp_bindx(new_sock->fd, (struct sockaddr *)addr_buf, + addr_count, SCTP_BINDX_ADD_ADDR); + if (rv < 0) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_bindx() failed to bind multiple addresses"); + goto err; + } + + /* + * Log debug info: only the first address is shown here as an example. + */ + ogs_debug("sctp_server() %s (bound %d addresses)", + ogs_sockaddr_to_string_static(sa_list), addr_count); + + /* Start listening for connections. */ + rv = ogs_sock_listen(new_sock); + ogs_assert(rv == OGS_OK); + + /* Success: free the buffer and return the socket. */ + ogs_free(addr_buf); + return new_sock; + +err: + if (addr_buf) + ogs_free(addr_buf); + if (new_sock) + ogs_sock_destroy(new_sock); + + /* + * On failure, log an error based on the first address + * in sa_list (customize as needed). + */ + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_server() %s failed", + ogs_sockaddr_to_string_static(sa_list)); + + return NULL; } ogs_sock_t *ogs_sctp_client( - int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) + int type, + ogs_sockaddr_t *sa_list, + ogs_sockaddr_t *local_sa_list, + ogs_sockopt_t *socket_option) { int rv; - char buf[OGS_ADDRSTRLEN]; - - ogs_sock_t *new = NULL; - ogs_sockaddr_t *addr; + int sa_family; + ogs_sock_t *new_sock = NULL; ogs_sockopt_t option; + /* Buffers and counters for remote addresses. */ + unsigned char *remote_buf = NULL; + int remote_count = 0; + int remote_len = 0; + + /* Buffers and counters for local addresses (if provided). */ + unsigned char *local_buf = NULL; + int local_count = 0; + int local_len = 0; + ogs_assert(sa_list); + /* Initialize socket options and copy user-provided options if present. */ ogs_sockopt_init(&option); if (socket_option) - memcpy(&option, socket_option, sizeof option); + memcpy(&option, socket_option, sizeof(option)); - addr = sa_list; - while (addr) { - new = ogs_sctp_socket(addr->ogs_sa_family, type); - if (new) { - rv = ogs_sctp_peer_addr_params(new, &option); - ogs_assert(rv == OGS_OK); - - rv = ogs_sctp_rto_info(new, &option); - ogs_assert(rv == OGS_OK); - - rv = ogs_sctp_initmsg(new, &option); - ogs_assert(rv == OGS_OK); - - if (option.sctp_nodelay == true) { - rv = ogs_sctp_nodelay(new, true); - ogs_assert(rv == OGS_OK); - } else - ogs_warn("SCTP NO_DELAY Disabled"); - - if (option.so_linger.l_onoff == true) { - rv = ogs_sctp_so_linger(new, option.so_linger.l_linger); - ogs_assert(rv == OGS_OK); - } - - if (ogs_sock_connect(new, addr) == OGS_OK) { - ogs_debug("sctp_client() [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); - break; - } - - ogs_sock_destroy(new); - } - - addr = addr->next; + /* + * Build the contiguous buffer for REMOTE addresses using our helper + * function. This will be used later by sctp_connectx(). + */ + remote_buf = create_continuous_address_buffer( + sa_list, &remote_count, &remote_len); + if (!remote_buf) { + ogs_error("create_continuous_address_buffer() failed"); + goto err; } - if (addr == NULL) { + /* Determine the appropriate address family from sa_list */ + sa_family = sctp_socket_family_from_addr_list(sa_list); + if (sa_family == AF_UNSPEC) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "sctp_client() [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); - return NULL; + "sctp_client() No suitable address family found " + "in sa_list"); + goto err; } - ogs_assert(new); + /* Create the SCTP socket using the determined address family */ + new_sock = ogs_sctp_socket(sa_family, type); - return new; + /* Configure SCTP-specific options. */ + rv = ogs_sctp_peer_addr_params(new_sock, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_rto_info(new_sock, &option); + ogs_assert(rv == OGS_OK); + + rv = ogs_sctp_initmsg(new_sock, &option); + ogs_assert(rv == OGS_OK); + + if (option.sctp_nodelay == true) { + rv = ogs_sctp_nodelay(new_sock, true); + ogs_assert(rv == OGS_OK); + } else { + ogs_warn("SCTP NO_DELAY Disabled"); + } + + if (option.so_linger.l_onoff == true) { + rv = ogs_sctp_so_linger(new_sock, option.so_linger.l_linger); + ogs_assert(rv == OGS_OK); + } + + /* + * If local_sa_list is provided, bind those addresses before connecting. + * (Optional: some clients do not need explicit local bind.) + */ + if (local_sa_list) { + local_buf = create_continuous_address_buffer( + local_sa_list, &local_count, &local_len); + if (!local_buf) { + /* Error already logged. */ + goto err; + } + /* We can bind them using sctp_bindx() if desired. */ + rv = sctp_bindx(new_sock->fd, + (struct sockaddr *)local_buf, + local_count, + SCTP_BINDX_ADD_ADDR); + if (rv < 0) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_client() bind local addresses failed"); + goto err; + } + ogs_debug("sctp_client() bound %d local addresses", local_count); + } + + /* + * Connect to the REMOTE addresses using sctp_connectx(). + * (struct sockaddr *)remote_buf is the contiguous buffer. + */ + rv = sctp_connectx(new_sock->fd, + (struct sockaddr *)remote_buf, + remote_count, + NULL /* assoc_id */); + if (rv < 0) { + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_connectx() failed to connect"); + goto err; + } + + /* Debug log for the first remote address. */ + ogs_debug("sctp_client() connected to %s", + ogs_sockaddr_to_string_static(sa_list)); + + /* Success: free buffers and return the new socket. */ + if (local_buf) + ogs_free(local_buf); + if (remote_buf) + ogs_free(remote_buf); + return new_sock; + +err: + if (local_buf) + ogs_free(local_buf); + if (remote_buf) + ogs_free(remote_buf); + if (new_sock) + ogs_sock_destroy(new_sock); + + /* + * On failure, log an error based on the first remote address. + * Adjust to your needs, e.g., log local too if necessary. + */ + ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, + "sctp_client() %s failed", + ogs_sockaddr_to_string_static(sa_list)); + + return NULL; } int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) @@ -211,8 +440,9 @@ int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) if (addr == NULL) { ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, - "sctp_connect() [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + "sctp_connect() %s failed", + ogs_sockaddr_to_string_static(sa_list)); + return OGS_ERROR; } diff --git a/lib/sctp/ogs-sctp.h b/lib/sctp/ogs-sctp.h index 3384a98df..f698bf6af 100644 --- a/lib/sctp/ogs-sctp.h +++ b/lib/sctp/ogs-sctp.h @@ -109,7 +109,9 @@ ogs_sock_t *ogs_sctp_socket(int family, int type); ogs_sock_t *ogs_sctp_server( int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); ogs_sock_t *ogs_sctp_client( - int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option); + int type, + ogs_sockaddr_t *sa_list, ogs_sockaddr_t *local_sa_list, + ogs_sockopt_t *socket_option); int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list); int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list); diff --git a/lib/sctp/ogs-usrsctp.c b/lib/sctp/ogs-usrsctp.c index 60675ca93..a587fbcae 100644 --- a/lib/sctp/ogs-usrsctp.c +++ b/lib/sctp/ogs-usrsctp.c @@ -142,8 +142,8 @@ ogs_sock_t *ogs_sctp_server( } if (addr == NULL) { - ogs_error("sctp_server [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_error("sctp_server %s failed", + ogs_sockaddr_to_string_static(sa_list)); return NULL; } @@ -156,7 +156,9 @@ ogs_sock_t *ogs_sctp_server( } ogs_sock_t *ogs_sctp_client( - int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option) + int type, + ogs_sockaddr_t *sa_list, ogs_sockaddr_t *local_sa_list, + ogs_sockopt_t *socket_option) { int rv; char buf[OGS_ADDRSTRLEN]; @@ -208,8 +210,8 @@ ogs_sock_t *ogs_sctp_client( } if (addr == NULL) { - ogs_error("sctp_client [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_error("sctp_client %s failed", + ogs_sockaddr_to_string_static(sa_list)); return NULL; } @@ -219,7 +221,6 @@ ogs_sock_t *ogs_sctp_client( int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) { struct socket *socket = (struct socket *)sock; - char buf[OGS_ADDRSTRLEN]; socklen_t addrlen; ogs_assert(socket); @@ -229,13 +230,13 @@ int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) ogs_assert(addrlen); if (usrsctp_bind(socket, &sa_list->sa, addrlen) != 0) { - ogs_error("sctp_bind() [%s]:%d failed", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_error("sctp_bind() %s failed", + ogs_sockaddr_to_string_static(sa_list)); + return OGS_ERROR; } - ogs_debug("sctp_bind() [%s]:%d", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_debug("sctp_bind() %s", ogs_sockaddr_to_string_static(sa_list)); return OGS_OK; } @@ -243,7 +244,6 @@ int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) { struct socket *socket = (struct socket *)sock; - char buf[OGS_ADDRSTRLEN]; socklen_t addrlen; ogs_assert(socket); @@ -253,13 +253,11 @@ int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list) ogs_assert(addrlen); if (usrsctp_connect(socket, &sa_list->sa, addrlen) != 0) { - ogs_error("sctp_connect() [%s]:%d", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_error("sctp_connect() %s", ogs_sockaddr_to_string_static(sa_list)); return OGS_ERROR; } - ogs_debug("sctp_connect() [%s]:%d", - OGS_ADDR(sa_list, buf), OGS_PORT(sa_list)); + ogs_debug("sctp_connect() %s", ogs_sockaddr_to_string_static(sa_list)); return OGS_OK; } diff --git a/meson.build b/meson.build index b3befad2b..c54a57768 100644 --- a/meson.build +++ b/meson.build @@ -57,7 +57,7 @@ if clangtidy.found() != true endif meson.add_install_script(python3_exe, '-c', - mkdir_p.format(join_paths(localstatedir, 'log', 'open5gs'))) + mkdir_p.format(join_paths(localstatedir, 'log', 'open5gs', 'tls'))) # Compiler flags if cc.get_id() == 'gcc' or cc.get_id() == 'clang' diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index 49a9a6f66..652f711da 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -845,6 +845,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) if (!gnb) { ogs_error("amf_gnb_add() failed"); ogs_free(addr); + break; } } else { ogs_free(addr); diff --git a/src/amf/context.c b/src/amf/context.c index 10204f7d1..676db8e17 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1258,7 +1258,8 @@ void amf_gnb_remove(amf_gnb_t *gnb) ogs_hash_set(self.gnb_addr_hash, gnb->sctp.addr, sizeof(ogs_sockaddr_t), NULL); - ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL); + if (gnb->gnb_id_presence == true) + ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL); ogs_sctp_flush_and_destroy(&gnb->sctp); @@ -1294,11 +1295,14 @@ int amf_gnb_set_gnb_id(amf_gnb_t *gnb, uint32_t gnb_id) { ogs_assert(gnb); - ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL); + if (gnb->gnb_id_presence == true) + ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), NULL); gnb->gnb_id = gnb_id; ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), gnb); + gnb->gnb_id_presence = true; + return OGS_OK; } @@ -2261,6 +2265,7 @@ amf_sess_t *amf_sess_add(amf_ue_t *amf_ue, uint8_t psi) sess->s_nssai.sst = 0; sess->s_nssai.sd.v = OGS_S_NSSAI_NO_SD_VALUE; + sess->mapped_hplmn_presence = false; sess->mapped_hplmn.sst = 0; sess->mapped_hplmn.sd.v = OGS_S_NSSAI_NO_SD_VALUE; @@ -2863,6 +2868,8 @@ bool amf_update_allowed_nssai(amf_ue_t *amf_ue) allowed->sst = requested->sst; allowed->sd.v = requested->sd.v; + allowed->mapped_hplmn_sst_presence = + requested->mapped_hplmn_sst_presence; allowed->mapped_hplmn_sst = requested->mapped_hplmn_sst; allowed->mapped_hplmn_sd.v = requested->mapped_hplmn_sd.v; @@ -2899,6 +2906,7 @@ bool amf_update_allowed_nssai(amf_ue_t *amf_ue) allowed->sst = slice->s_nssai.sst; allowed->sd.v = slice->s_nssai.sd.v; + allowed->mapped_hplmn_sst_presence = false; allowed->mapped_hplmn_sst = 0; allowed->mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; diff --git a/src/amf/context.h b/src/amf/context.h index 7d188aa1e..d849ee7de 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -139,6 +139,7 @@ typedef struct amf_gnb_s { ogs_fsm_t sm; /* A state machine */ + bool gnb_id_presence; uint32_t gnb_id; /* gNB_ID received from gNB */ ogs_plmn_id_t plmn_id; /* gNB PLMN-ID received from gNB */ ogs_sctp_sock_t sctp; /* SCTP socket */ @@ -835,6 +836,7 @@ typedef struct amf_sess_s { ogs_s_nssai_t s_nssai; ogs_s_nssai_t mapped_hplmn; + bool mapped_hplmn_presence; char *dnn; bool lbo_roaming_allowed; diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 4474234b0..c3e87d8c0 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -1290,6 +1290,12 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue, if (ie.sst == amf_ue->slice[i].s_nssai.sst && ie.sd.v == amf_ue->slice[i].s_nssai.sd.v) { + if (ie.mapped_hplmn_sst_presence) { + sess->mapped_hplmn_presence = true; + sess->mapped_hplmn.sst = ie.mapped_hplmn_sst; + sess->mapped_hplmn.sd.v = ie.mapped_hplmn_sd.v; + } + /* PASS */ } else { diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index f17cae690..123a779e4 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -547,61 +547,64 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) SWITCH(sbi_message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS) SWITCH(sbi_message->h.resource.component[2]) - CASE(OGS_SBI_RESOURCE_NAME_TRANSFER) + CASE(OGS_SBI_RESOURCE_NAME_TRANSFER) - r = OGS_ERROR; - - if (sbi_message->res_status == OGS_SBI_HTTP_STATUS_OK) { - amf_ue->amf_ue_context_transfer_state = UE_CONTEXT_TRANSFER_NEW_AMF_STATE; - r = amf_namf_comm_handle_ue_context_transfer_response( - sbi_message, amf_ue); - if (r != OGS_OK) { - ogs_error("failed to handle " - "UE_CONTEXT_TRANSFER response"); - amf_ue->amf_ue_context_transfer_state = UE_CONTEXT_INITIAL_STATE; - } - } else { - ogs_error("[%s] HTTP response error [%d]", - amf_ue->suci, sbi_message->res_status); - amf_ue->amf_ue_context_transfer_state = UE_CONTEXT_INITIAL_STATE; - } + r = OGS_ERROR; + if (sbi_message->res_status == OGS_SBI_HTTP_STATUS_OK) { + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_TRANSFER_NEW_AMF_STATE; + r = amf_namf_comm_handle_ue_context_transfer_response( + sbi_message, amf_ue); if (r != OGS_OK) { - if (!(AMF_UE_HAVE_SUCI(amf_ue) || - AMF_UE_HAVE_SUPI(amf_ue))) { - CLEAR_AMF_UE_TIMER(amf_ue->t3570); - r = nas_5gs_send_identity_request(amf_ue); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - break; - } + ogs_error("failed to handle " + "UE_CONTEXT_TRANSFER response"); + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_INITIAL_STATE; } + } else { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->suci, sbi_message->res_status); + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_INITIAL_STATE; + } - xact_count = amf_sess_xact_count(amf_ue); - amf_sbi_send_release_all_sessions( - ran_ue_find_by_id(amf_ue->ran_ue_id), amf_ue, - AMF_RELEASE_SM_CONTEXT_NO_STATE); - - if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && - amf_sess_xact_count(amf_ue) == xact_count) { - r = amf_ue_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, - amf_ue, 0, NULL); + if (r != OGS_OK) { + if (!(AMF_UE_HAVE_SUCI(amf_ue) || + AMF_UE_HAVE_SUPI(amf_ue))) { + CLEAR_AMF_UE_TIMER(amf_ue->t3570); + r = nas_5gs_send_identity_request(amf_ue); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); + break; } + } - OGS_FSM_TRAN(s, &gmm_state_authentication); - break; + xact_count = amf_sess_xact_count(amf_ue); + amf_sbi_send_release_all_sessions( + ran_ue_find_by_id(amf_ue->ran_ue_id), amf_ue, + AMF_RELEASE_SM_CONTEXT_NO_STATE); - DEFAULT - ogs_error("Invalid resource name [%s]", - sbi_message->h.resource.component[2]); - ogs_assert_if_reached(); - END + if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && + amf_sess_xact_count(amf_ue) == xact_count) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + + OGS_FSM_TRAN(s, &gmm_state_authentication); break; + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[2]); + ogs_assert_if_reached(); + END + break; + DEFAULT ogs_error("Invalid resource name [%s]", sbi_message->h.resource.component[0]); @@ -1173,6 +1176,75 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) END break; + CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM) + SWITCH(sbi_message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS) + SWITCH(sbi_message->h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_TRANSFER) + + r = OGS_ERROR; + + if (sbi_message->res_status == OGS_SBI_HTTP_STATUS_OK) { + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_TRANSFER_NEW_AMF_STATE; + r = amf_namf_comm_handle_ue_context_transfer_response( + sbi_message, amf_ue); + if (r != OGS_OK) { + ogs_error("failed to handle " + "UE_CONTEXT_TRANSFER response"); + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_INITIAL_STATE; + } + } else { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->suci, sbi_message->res_status); + amf_ue->amf_ue_context_transfer_state = + UE_CONTEXT_INITIAL_STATE; + } + + if (r != OGS_OK) { + if (!(AMF_UE_HAVE_SUCI(amf_ue) || + AMF_UE_HAVE_SUPI(amf_ue))) { + CLEAR_AMF_UE_TIMER(amf_ue->t3570); + r = nas_5gs_send_identity_request(amf_ue); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + break; + } + } + + xact_count = amf_sess_xact_count(amf_ue); + amf_sbi_send_release_all_sessions( + ran_ue_find_by_id(amf_ue->ran_ue_id), amf_ue, + AMF_RELEASE_SM_CONTEXT_NO_STATE); + + if (!AMF_SESSION_RELEASE_PENDING(amf_ue) && + amf_sess_xact_count(amf_ue) == xact_count) { + r = amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + + OGS_FSM_TRAN(s, &gmm_state_authentication); + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[2]); + ogs_assert_if_reached(); + END + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + DEFAULT ogs_error("Invalid service name [%s]", sbi_message->h.service.name); ogs_assert_if_reached(); @@ -1905,6 +1977,31 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e) END break; + CASE(OGS_SBI_SERVICE_NAME_NPCF_AM_POLICY_CONTROL) + SWITCH(sbi_message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_POLICIES) + SWITCH(sbi_message->h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_CREATED) { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->supi, sbi_message->res_status); + } + ogs_error("[%s] Ignore SBI message", amf_ue->supi); + break; + + DEFAULT + ogs_error("Unknown method [%s]", sbi_message->h.method); + ogs_assert_if_reached(); + END + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + DEFAULT ogs_error("Invalid service name [%s]", sbi_message->h.service.name); ogs_assert_if_reached(); @@ -2123,6 +2220,53 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e) ogs_assert(sbi_message); SWITCH(sbi_message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NAUSF_AUTH) + SWITCH(sbi_message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_UE_AUTHENTICATIONS) + + if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_CREATED && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_OK && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT) { + if (sbi_message->res_status == + OGS_SBI_HTTP_STATUS_NOT_FOUND) { + ogs_warn("[%s] Cannot find SUCI [%d]", + amf_ue->suci, sbi_message->res_status); + } else { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->suci, sbi_message->res_status); + } + } + + SWITCH(sbi_message->h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_PUT) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_DELETE) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + DEFAULT + ogs_error("[%s] Invalid HTTP method [%s]", + amf_ue->suci, sbi_message->h.method); + ogs_assert_if_reached(); + END + break; + + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA) + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA_CONFIRMATION) + CASE(OGS_SBI_RESOURCE_NAME_EAP_SESSION) + ogs_warn("[%s] Ignore SBI message", amf_ue->supi); + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM) SWITCH(sbi_message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS) @@ -2257,6 +2401,53 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) state = e->h.sbi.state; SWITCH(sbi_message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NAUSF_AUTH) + SWITCH(sbi_message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_UE_AUTHENTICATIONS) + + if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_CREATED && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_OK && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT) { + if (sbi_message->res_status == + OGS_SBI_HTTP_STATUS_NOT_FOUND) { + ogs_warn("[%s] Cannot find SUCI [%d]", + amf_ue->suci, sbi_message->res_status); + } else { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->suci, sbi_message->res_status); + } + } + + SWITCH(sbi_message->h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_PUT) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_DELETE) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + DEFAULT + ogs_error("[%s] Invalid HTTP method [%s]", + amf_ue->suci, sbi_message->h.method); + ogs_assert_if_reached(); + END + break; + + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA) + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA_CONFIRMATION) + CASE(OGS_SBI_RESOURCE_NAME_EAP_SESSION) + ogs_warn("[%s] Ignore SBI message", amf_ue->supi); + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + CASE(OGS_SBI_SERVICE_NAME_NUDM_UECM) SWITCH(sbi_message->h.resource.component[1]) @@ -2815,6 +3006,53 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) ogs_assert(ran_ue); SWITCH(sbi_message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NAUSF_AUTH) + SWITCH(sbi_message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_UE_AUTHENTICATIONS) + + if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_CREATED && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_OK && + sbi_message->res_status != OGS_SBI_HTTP_STATUS_NO_CONTENT) { + if (sbi_message->res_status == + OGS_SBI_HTTP_STATUS_NOT_FOUND) { + ogs_warn("[%s] Cannot find SUCI [%d]", + amf_ue->suci, sbi_message->res_status); + } else { + ogs_error("[%s] HTTP response error [%d]", + amf_ue->suci, sbi_message->res_status); + } + } + + SWITCH(sbi_message->h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_PUT) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + CASE(OGS_SBI_HTTP_METHOD_DELETE) + ogs_warn("[%s] Ignore SBI message", amf_ue->suci); + break; + DEFAULT + ogs_error("[%s] Invalid HTTP method [%s]", + amf_ue->suci, sbi_message->h.method); + ogs_assert_if_reached(); + END + break; + + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA) + CASE(OGS_SBI_RESOURCE_NAME_5G_AKA_CONFIRMATION) + CASE(OGS_SBI_RESOURCE_NAME_EAP_SESSION) + ogs_warn("[%s] Ignore SBI message", amf_ue->supi); + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message->h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM) SWITCH(sbi_message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS) diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index 15b350c52..bbb316bf6 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -38,14 +38,16 @@ static bool maximum_number_of_gnbs_is_reached(void) static bool gnb_plmn_id_is_foreign(amf_gnb_t *gnb) { - int i, j; - - for (i = 0; i < gnb->num_of_supported_ta_list; i++) { - for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) { - if (memcmp(&gnb->plmn_id, - &gnb->supported_ta_list[i].bplmn_list[j].plmn_id, - OGS_PLMN_ID_LEN) == 0) - return false; + int i, j, k; + for (i = 0; i < amf_self()->num_of_plmn_support; i++) { + for (j = 0; j < gnb->num_of_supported_ta_list; j++) { + for (k = 0; k < gnb->supported_ta_list[j].num_of_bplmn_list; k++) { + if (memcmp(&amf_self()->plmn_support[i].plmn_id, + &gnb->supported_ta_list[j].bplmn_list[k].plmn_id, + OGS_PLMN_ID_LEN) == 0){ + return false; + } + } } } diff --git a/src/amf/ngap-path.c b/src/amf/ngap-path.c index 47b221b36..8e284787f 100644 --- a/src/amf/ngap-path.c +++ b/src/amf/ngap-path.c @@ -168,6 +168,12 @@ int ngap_send_to_nas(ran_ue_t *ran_ue, ogs_assert(ran_ue); ogs_assert(nasPdu); + if (nasPdu->size == 0) { + ogs_error("Empty NAS PDU"); + ran_ue_remove(ran_ue); + return OGS_ERROR; + } + amf_ue = amf_ue_find_by_id(ran_ue->amf_ue_id); /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. diff --git a/src/amf/nsmf-build.c b/src/amf/nsmf-build.c index 78cda7e65..f7cf9c44f 100644 --- a/src/amf/nsmf-build.c +++ b/src/amf/nsmf-build.c @@ -117,7 +117,7 @@ ogs_sbi_request_t *amf_nsmf_pdusession_build_create_sm_context( sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); SmContextCreateData.s_nssai = &sNssai; - if (sess->mapped_hplmn.sst) { + if (sess->mapped_hplmn_presence) { hplmnSnssai.sst = sess->mapped_hplmn.sst; hplmnSnssai.sd = ogs_s_nssai_sd_to_string(sess->mapped_hplmn.sd); SmContextCreateData.hplmn_snssai = &hplmnSnssai; diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 4eba1d233..e9cc8e187 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -83,6 +83,11 @@ ogs_pkbuf_t *emm_build_attach_accept( if (mme_ue->network_access_mode == OGS_NETWORK_ACCESS_MODE_ONLY_PACKET) { /* permit only EPS_ATTACH */ eps_attach_result->result = OGS_NAS_ATTACH_TYPE_EPS_ATTACH; + if (ogs_global_conf()->parameter.fake_csfb == true) + eps_attach_result->result = + OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH; + else + eps_attach_result->result = OGS_NAS_ATTACH_TYPE_EPS_ATTACH; } else { eps_attach_result->result = mme_ue->nas_eps.attach.value; } diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index e1045f166..38f817ddf 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -667,7 +667,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e, } else { if (e->s1ap_code == S1AP_ProcedureCode_id_initialUEMessage) { - ogs_debug(" Iniital UE Message"); + ogs_debug(" Initial UE Message"); if (mme_ue->nas_eps.update.active_flag) { /* diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 6f1d412f9..426ea274a 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2050,9 +2050,9 @@ int mme_context_parse_config(void) while (ogs_yaml_iter_next(&sgsap_iter)) { const char *sgsap_key = ogs_yaml_iter_key(&sgsap_iter); ogs_assert(sgsap_key); - if (!strcmp(sgsap_key, "server")) { - ogs_yaml_iter_t server_iter, server_array; - ogs_yaml_iter_recurse(&sgsap_iter, &server_array); + if (!strcmp(sgsap_key, "client")) { + ogs_yaml_iter_t client_iter, client_array; + ogs_yaml_iter_recurse(&sgsap_iter, &client_array); do { mme_vlr_t *vlr = NULL; ogs_plmn_id_t plmn_id; @@ -2063,38 +2063,39 @@ int mme_context_parse_config(void) const char *tac, *lac; } map[MAX_NUM_OF_CSMAP]; int map_num = 0; - ogs_sockaddr_t *addr = NULL; + ogs_sockaddr_t *addr = NULL, *local_addr = NULL; int family = AF_UNSPEC; - int i, hostname_num = 0; - const char *hostname[OGS_MAX_NUM_OF_HOSTNAME]; + int i, hostname_num = 0, local_hostname_num = 0; + const char *hostname[OGS_MAX_NUM_OF_HOSTNAME], + *local_hostname[OGS_MAX_NUM_OF_HOSTNAME]; uint16_t port = self.sgsap_port; ogs_sockopt_t option; bool is_option = false; - if (ogs_yaml_iter_type(&server_array) == + if (ogs_yaml_iter_type(&client_array) == YAML_MAPPING_NODE) { - memcpy(&server_iter, &server_array, + memcpy(&client_iter, &client_array, sizeof(ogs_yaml_iter_t)); - } else if (ogs_yaml_iter_type(&server_array) == + } else if (ogs_yaml_iter_type(&client_array) == YAML_SEQUENCE_NODE) { - if (!ogs_yaml_iter_next(&server_array)) + if (!ogs_yaml_iter_next(&client_array)) break; ogs_yaml_iter_recurse( - &server_array, &server_iter); - } else if (ogs_yaml_iter_type(&server_array) == + &client_array, &client_iter); + } else if (ogs_yaml_iter_type(&client_array) == YAML_SCALAR_NODE) { break; } else ogs_assert_if_reached(); - while (ogs_yaml_iter_next(&server_iter)) { - const char *server_key = - ogs_yaml_iter_key(&server_iter); - ogs_assert(server_key); - if (!strcmp(server_key, "family")) { + while (ogs_yaml_iter_next(&client_iter)) { + const char *client_key = + ogs_yaml_iter_key(&client_iter); + ogs_assert(client_key); + if (!strcmp(client_key, "family")) { const char *v = - ogs_yaml_iter_value(&server_iter); + ogs_yaml_iter_value(&client_iter); if (v) family = atoi(v); if (family != AF_UNSPEC && family != AF_INET && @@ -2106,9 +2107,9 @@ int mme_context_parse_config(void) AF_UNSPEC, AF_INET, AF_INET6); family = AF_UNSPEC; } - } else if (!strcmp(server_key, "address")) { + } else if (!strcmp(client_key, "address")) { ogs_yaml_iter_t hostname_iter; - ogs_yaml_iter_recurse(&server_iter, + ogs_yaml_iter_recurse(&client_iter, &hostname_iter); ogs_assert(ogs_yaml_iter_type( &hostname_iter) != @@ -2131,26 +2132,53 @@ int mme_context_parse_config(void) } while (ogs_yaml_iter_type( &hostname_iter) == YAML_SEQUENCE_NODE); - } else if (!strcmp(server_key, "port")) { + } else if (!strcmp(client_key, + "local_address")) { + ogs_yaml_iter_t local_hostname_iter; + ogs_yaml_iter_recurse(&client_iter, + &local_hostname_iter); + ogs_assert(ogs_yaml_iter_type( + &local_hostname_iter) != + YAML_MAPPING_NODE); + + do { + if (ogs_yaml_iter_type( + &local_hostname_iter) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next( + &local_hostname_iter)) + break; + } + + ogs_assert(local_hostname_num < + OGS_MAX_NUM_OF_HOSTNAME); + local_hostname + [local_hostname_num++] = + ogs_yaml_iter_value( + &local_hostname_iter); + } while (ogs_yaml_iter_type( + &local_hostname_iter) == + YAML_SEQUENCE_NODE); + } else if (!strcmp(client_key, "port")) { const char *v = - ogs_yaml_iter_value(&server_iter); + ogs_yaml_iter_value(&client_iter); if (v) { port = atoi(v); self.sgsap_port = port; } - } else if (!strcmp(server_key, "option")) { + } else if (!strcmp(client_key, "option")) { rv = ogs_app_parse_sockopt_config( - &server_iter, &option); + &client_iter, &option); if (rv != OGS_OK) { ogs_error("ogs_app_parse_sockopt_" "config() failed"); return rv; } is_option = true; - } else if (!strcmp(server_key, "map")) { + } else if (!strcmp(client_key, "map")) { ogs_yaml_iter_t map_iter; ogs_yaml_iter_recurse( - &server_iter, &map_iter); + &client_iter, &map_iter); map[map_num].tai_mcc = NULL; map[map_num].tai_mnc = NULL; @@ -2320,13 +2348,13 @@ int mme_context_parse_config(void) map_num++; - } else if (!strcmp(server_key, "tai")) { + } else if (!strcmp(client_key, "tai")) { ogs_error( "tai/lai configuraton changed to " "map.tai/map.lai"); ogs_log_print(OGS_LOG_ERROR, "sgsap:\n" - " server\n" + " client\n" " address: 127.0.0.2\n" " map:\n" " tai:\n" @@ -2340,13 +2368,13 @@ int mme_context_parse_config(void) " mnc: 01\n" " lac: 43691\n"); return OGS_ERROR; - } else if (!strcmp(server_key, "lai")) { + } else if (!strcmp(client_key, "lai")) { ogs_error( "tai/lai configuraton changed to " "map.tai/map.lai"); ogs_log_print(OGS_LOG_ERROR, "sgsap:\n" - " server\n" + " client\n" " address: 127.0.0.2\n" " map:\n" " tai:\n" @@ -2362,7 +2390,7 @@ int mme_context_parse_config(void) return OGS_ERROR; } else ogs_warn("unknown key `%s`", - server_key); + client_key); } @@ -2386,7 +2414,20 @@ int mme_context_parse_config(void) if (addr == NULL) continue; - vlr = mme_vlr_add(addr, + local_addr = NULL; + for (i = 0; i < local_hostname_num; i++) { + rv = ogs_addaddrinfo(&local_addr, + family, local_hostname[i], port, 0); + ogs_assert(rv == OGS_OK); + } + + ogs_filter_ip_version(&local_addr, + ogs_global_conf()->parameter.no_ipv4, + ogs_global_conf()->parameter.no_ipv6, + ogs_global_conf()->parameter. + prefer_ipv4); + + vlr = mme_vlr_add(addr, local_addr, is_option ? &option : NULL); ogs_assert(vlr); @@ -2409,7 +2450,7 @@ int mme_context_parse_config(void) &csmap->lai.nas_plmn_id, &plmn_id); csmap->lai.lac = atoi(map[i].lac); } - } while (ogs_yaml_iter_type(&server_array) == + } while (ogs_yaml_iter_type(&client_array) == YAML_SEQUENCE_NODE); } else ogs_warn("unknown key `%s`", sgsap_key); @@ -2737,7 +2778,10 @@ ogs_sockaddr_t *mme_pgw_addr_find_by_apn_enb( return NULL; } -mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list, ogs_sockopt_t *option) +mme_vlr_t *mme_vlr_add( + ogs_sockaddr_t *sa_list, + ogs_sockaddr_t *local_sa_list, + ogs_sockopt_t *option) { mme_vlr_t *vlr = NULL; @@ -2751,6 +2795,7 @@ mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list, ogs_sockopt_t *option) vlr->ostream_id = 0; vlr->sa_list = sa_list; + vlr->local_sa_list = local_sa_list; if (option) { vlr->max_num_of_ostreams = option->sctp.sinit_num_ostreams; vlr->option = ogs_memdup(option, sizeof *option); @@ -2770,6 +2815,7 @@ void mme_vlr_remove(mme_vlr_t *vlr) mme_vlr_close(vlr); ogs_freeaddrinfo(vlr->sa_list); + ogs_freeaddrinfo(vlr->local_sa_list); if (vlr->option) ogs_free(vlr->option); @@ -2794,13 +2840,13 @@ void mme_vlr_close(mme_vlr_t *vlr) ogs_sctp_destroy(vlr->sock); } -mme_vlr_t *mme_vlr_find_by_addr(const ogs_sockaddr_t *addr) +mme_vlr_t *mme_vlr_find_by_sock(const ogs_sock_t *sock) { mme_vlr_t *vlr = NULL; - ogs_assert(addr); + ogs_assert(sock); ogs_list_for_each(&self.vlr_list, vlr) { - if (ogs_sockaddr_is_equal(vlr->addr, addr) == true) + if (vlr->sock == sock) return vlr; } @@ -2999,7 +3045,8 @@ int mme_enb_remove(mme_enb_t *enb) ogs_hash_set(self.enb_addr_hash, enb->sctp.addr, sizeof(ogs_sockaddr_t), NULL); - ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL); + if (enb->enb_id_presence == true) + ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL); /* * CHECK: @@ -3046,11 +3093,14 @@ int mme_enb_set_enb_id(mme_enb_t *enb, uint32_t enb_id) { ogs_assert(enb); - ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL); + if (enb->enb_id_presence == true) + ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), NULL); enb->enb_id = enb_id; ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), enb); + enb->enb_id_presence = true; + return OGS_OK; } diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 2300099e4..4452bbbed 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -216,9 +216,9 @@ typedef struct mme_vlr_s { uint16_t ostream_id; /* vlr_ostream_id generator */ ogs_sockaddr_t *sa_list; /* VLR SGsAP Socket Address List */ + ogs_sockaddr_t *local_sa_list; /* VLR SGsAP Socket Local Address List */ ogs_sock_t *sock; /* VLR SGsAP Socket */ - ogs_sockaddr_t *addr; /* VLR SGsAP Connected Socket Address */ ogs_sockopt_t *option; /* VLR SGsAP Socket Option */ ogs_poll_t *poll; /* VLR SGsAP Poll */ } mme_vlr_t; @@ -246,6 +246,7 @@ typedef struct mme_enb_s { ogs_fsm_t sm; /* A state machine */ + bool enb_id_presence; uint32_t enb_id; /* eNB_ID received from eNB */ ogs_plmn_id_t plmn_id; /* eNB PLMN-ID received from eNB */ ogs_sctp_sock_t sctp; /* SCTP socket */ @@ -937,11 +938,14 @@ void mme_pgw_remove_all(void); ogs_sockaddr_t *mme_pgw_addr_find_by_apn_enb( ogs_list_t *list, int family, const mme_sess_t *sess); -mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list, ogs_sockopt_t *option); +mme_vlr_t *mme_vlr_add( + ogs_sockaddr_t *sa_list, + ogs_sockaddr_t *local_sa_list, + ogs_sockopt_t *option); void mme_vlr_remove(mme_vlr_t *vlr); void mme_vlr_remove_all(void); void mme_vlr_close(mme_vlr_t *vlr); -mme_vlr_t *mme_vlr_find_by_addr(const ogs_sockaddr_t *addr); +mme_vlr_t *mme_vlr_find_by_sock(const ogs_sock_t *sock); mme_csmap_t *mme_csmap_add(mme_vlr_t *vlr); void mme_csmap_remove(mme_csmap_t *csmap); diff --git a/src/mme/mme-event.c b/src/mme/mme-event.c index 483b02b12..42ce405d7 100644 --- a/src/mme/mme-event.c +++ b/src/mme/mme-event.c @@ -117,7 +117,6 @@ void mme_sctp_event_push(mme_event_e id, ogs_assert(id); ogs_assert(sock); - ogs_assert(addr); e = mme_event_new(id); ogs_assert(e); diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 7cc0d4c63..6a06fd3e2 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -970,25 +970,19 @@ cleanup: case MME_EVENT_SGSAP_LO_SCTP_COMM_UP: sock = e->sock; ogs_assert(sock); - addr = e->addr; - ogs_assert(addr); - - ogs_assert(addr->ogs_sa_family == AF_INET || - addr->ogs_sa_family == AF_INET6); max_num_of_ostreams = e->max_num_of_ostreams; - vlr = mme_vlr_find_by_addr(addr); - ogs_free(addr); - + vlr = mme_vlr_find_by_sock(sock); ogs_assert(vlr); ogs_assert(OGS_FSM_STATE(&vlr->sm)); vlr->max_num_of_ostreams = ogs_min(max_num_of_ostreams, vlr->max_num_of_ostreams); - ogs_debug("VLR-SGs SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]", - OGS_ADDR(vlr->addr, buf), vlr->max_num_of_ostreams); + ogs_debug("VLR-SGs SCTP_COMM_UP %s Max Num of Outbound Streams[%d]", + ogs_sockaddr_to_string_static(vlr->sa_list), + vlr->max_num_of_ostreams); e->vlr = vlr; ogs_fsm_dispatch(&vlr->sm, e); @@ -997,15 +991,8 @@ cleanup: case MME_EVENT_SGSAP_LO_CONNREFUSED: sock = e->sock; ogs_assert(sock); - addr = e->addr; - ogs_assert(addr); - - ogs_assert(addr->ogs_sa_family == AF_INET || - addr->ogs_sa_family == AF_INET6); - - vlr = mme_vlr_find_by_addr(addr); - ogs_free(addr); + vlr = mme_vlr_find_by_sock(sock); ogs_assert(vlr); ogs_assert(OGS_FSM_STATE(&vlr->sm)); @@ -1013,29 +1000,22 @@ cleanup: e->vlr = vlr; ogs_fsm_dispatch(&vlr->sm, e); - ogs_info("VLR-SGs[%s] connection refused!!!", - OGS_ADDR(vlr->addr, buf)); + ogs_info("VLR-SGs %s connection refused!!!", + ogs_sockaddr_to_string_static(vlr->sa_list)); } else { - ogs_warn("VLR-SGs[%s] connection refused, Already Removed!", - OGS_ADDR(vlr->addr, buf)); + ogs_warn("VLR-SGs %s connection refused, Already Removed!", + ogs_sockaddr_to_string_static(vlr->sa_list)); } break; case MME_EVENT_SGSAP_MESSAGE: sock = e->sock; ogs_assert(sock); - addr = e->addr; - ogs_assert(addr); pkbuf = e->pkbuf; ogs_assert(pkbuf); - ogs_assert(addr->ogs_sa_family == AF_INET || - addr->ogs_sa_family == AF_INET6); - - vlr = mme_vlr_find_by_addr(addr); - ogs_free(addr); - + vlr = mme_vlr_find_by_sock(sock); ogs_assert(vlr); ogs_assert(OGS_FSM_STATE(&vlr->sm)); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 3ce728382..618b42bb6 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -50,12 +50,17 @@ static bool maximum_number_of_enbs_is_reached(void) static bool enb_plmn_id_is_foreign(mme_enb_t *enb) { - int i; + int i, j, k; - for (i = 0; i < enb->num_of_supported_ta_list; i++) { - if (memcmp(&enb->plmn_id, &enb->supported_ta_list[i].plmn_id, - OGS_PLMN_ID_LEN) == 0) - return false; + for (i = 0; i < mme_self()->num_of_served_gummei; i++) { + for (j = 0; j < mme_self()->served_gummei[i].num_of_plmn_id; j++) { + for (k = 0; k < enb->num_of_supported_ta_list; k++) { + if (memcmp(&mme_self()->served_gummei[i].plmn_id[j], + &enb->supported_ta_list[k].plmn_id, + OGS_PLMN_ID_LEN) == 0) + return false; + } + } } return true; diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 0ddc68c9e..ddbdb336d 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -173,6 +173,12 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue, ogs_assert(enb_ue); ogs_assert(nasPdu); + if (nasPdu->size == 0) { + ogs_error("Empty NAS PDU"); + enb_ue_remove(enb_ue); + return OGS_ERROR; + } + mme_ue = mme_ue_find_by_id(enb_ue->mme_ue_id); /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index a42915aa1..2fbdfb2b1 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -53,8 +53,7 @@ void sgsap_close(void) } } -int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, - ogs_sockaddr_t *addr, uint16_t stream_no) +int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, uint16_t stream_no) { int sent; @@ -62,7 +61,7 @@ int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, ogs_assert(pkbuf); sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len, - addr, OGS_SCTP_SGSAP_PPID, stream_no); + NULL, OGS_SCTP_SGSAP_PPID, stream_no); if (sent < 0 || sent != pkbuf->len) { ogs_error("ogs_sctp_sendmsg(len:%d,ssn:%d) error (%d:%s)", pkbuf->len, stream_no, errno, strerror(errno)); @@ -77,7 +76,6 @@ int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, int sgsap_send_to_vlr_with_sid( mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf, uint16_t stream_no) { - char buf[OGS_ADDRSTRLEN]; ogs_sock_t *sock = NULL;; ogs_assert(vlr); @@ -85,8 +83,10 @@ int sgsap_send_to_vlr_with_sid( sock = vlr->sock; ogs_assert(sock); - ogs_debug(" VLR-IP[%s]", OGS_ADDR(vlr->addr, buf)); - return sgsap_send(sock, pkbuf, vlr->addr, stream_no); + ogs_debug(" StreamNO[%d] VLR-IP[%s]", + stream_no, ogs_sockaddr_to_string_static(vlr->sa_list)); + + return sgsap_send(sock, pkbuf, stream_no); } int sgsap_send_to_vlr(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf) diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index 0c22996a8..897019c9b 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -36,8 +36,7 @@ void sgsap_close(void); ogs_sock_t *sgsap_client(mme_vlr_t *vlr); -int sgsap_send(ogs_sock_t *sock, - ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr, uint16_t stream_no); +int sgsap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf, uint16_t stream_no); int sgsap_send_to_vlr_with_sid( mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf, uint16_t stream_no); diff --git a/src/mme/sgsap-sctp.c b/src/mme/sgsap-sctp.c index d14c9287e..e7c8d340c 100644 --- a/src/mme/sgsap-sctp.c +++ b/src/mme/sgsap-sctp.c @@ -34,26 +34,24 @@ static void recv_handler(ogs_sock_t *sock); ogs_sock_t *sgsap_client(mme_vlr_t *vlr) { - char buf[OGS_ADDRSTRLEN]; ogs_sock_t *sock = NULL; ogs_assert(vlr); - sock = ogs_sctp_client(SOCK_SEQPACKET, vlr->sa_list, vlr->option); + sock = ogs_sctp_client(SOCK_STREAM, + vlr->sa_list, vlr->local_sa_list, vlr->option); if (sock) { vlr->sock = sock; #if HAVE_USRSCTP - vlr->addr = vlr->sa_list; usrsctp_set_non_blocking((struct socket *)sock, 1); usrsctp_set_upcall((struct socket *)sock, usrsctp_recv_handler, NULL); #else - vlr->addr = &sock->remote_addr; vlr->poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, lksctp_recv_handler, sock); ogs_assert(vlr->poll); #endif - ogs_info("sgsap client() [%s]:%d", - OGS_ADDR(vlr->addr, buf), OGS_PORT(vlr->addr)); + ogs_info("sgsap client() %s", + ogs_sockaddr_to_string_static(vlr->sa_list)); } return sock; @@ -86,8 +84,6 @@ static void recv_handler(ogs_sock_t *sock) { ogs_pkbuf_t *pkbuf; int size; - ogs_sockaddr_t *addr = NULL; - ogs_sockaddr_t from; ogs_sctp_info_t sinfo; int flags = 0; @@ -97,7 +93,7 @@ static void recv_handler(ogs_sock_t *sock) ogs_assert(pkbuf); ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN); size = ogs_sctp_recvmsg( - sock, pkbuf->data, pkbuf->len, &from, &sinfo, &flags); + sock, pkbuf->data, pkbuf->len, NULL, &sinfo, &flags); if (size < 0 || size >= OGS_MAX_SDU_LEN) { ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s)", size, errno, strerror(errno)); @@ -122,12 +118,8 @@ static void recv_handler(ogs_sock_t *sock) if (not->sn_assoc_change.sac_state == SCTP_COMM_UP) { ogs_debug("SCTP_COMM_UP"); - addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(addr); - memcpy(addr, &from, sizeof(ogs_sockaddr_t)); - sgsap_event_push(MME_EVENT_SGSAP_LO_SCTP_COMM_UP, - sock, addr, NULL, + sock, NULL, NULL, not->sn_assoc_change.sac_inbound_streams, not->sn_assoc_change.sac_outbound_streams); } else if (not->sn_assoc_change.sac_state == SCTP_SHUTDOWN_COMP || @@ -138,12 +130,8 @@ static void recv_handler(ogs_sock_t *sock) if (not->sn_assoc_change.sac_state == SCTP_COMM_LOST) ogs_debug("SCTP_COMM_LOST"); - addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(addr); - memcpy(addr, &from, sizeof(ogs_sockaddr_t)); - sgsap_event_push(MME_EVENT_SGSAP_LO_CONNREFUSED, - sock, addr, NULL, 0, 0); + sock, NULL, NULL, 0, 0); } break; case SCTP_SHUTDOWN_EVENT : @@ -166,12 +154,8 @@ static void recv_handler(ogs_sock_t *sock) not->sn_send_failed.ssf_error); #endif - addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(addr); - memcpy(addr, &from, sizeof(ogs_sockaddr_t)); - sgsap_event_push(MME_EVENT_SGSAP_LO_CONNREFUSED, - sock, addr, NULL, 0, 0); + sock, NULL, NULL, 0, 0); break; case SCTP_PEER_ADDR_CHANGE: ogs_warn("SCTP_PEER_ADDR_CHANGE:[T:%d, F:0x%x, S:%d]", @@ -193,11 +177,7 @@ static void recv_handler(ogs_sock_t *sock) } else if (flags & MSG_EOR) { ogs_pkbuf_trim(pkbuf, size); - addr = ogs_calloc(1, sizeof(ogs_sockaddr_t)); - ogs_assert(addr); - memcpy(addr, &from, sizeof(ogs_sockaddr_t)); - - sgsap_event_push(MME_EVENT_SGSAP_MESSAGE, sock, addr, pkbuf, 0, 0); + sgsap_event_push(MME_EVENT_SGSAP_MESSAGE, sock, NULL, pkbuf, 0, 0); return; } else { if (ogs_socket_errno != OGS_EAGAIN) { diff --git a/src/nrf/nnrf-handler.c b/src/nrf/nnrf-handler.c index 8ef71a588..8e0b01d8b 100644 --- a/src/nrf/nnrf-handler.c +++ b/src/nrf/nnrf-handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2023 by Sukchan Lee + * Copyright (C) 2019-2024 by Sukchan Lee * * This file is part of Open5GS. * @@ -25,6 +25,15 @@ static int discover_handler( static void handle_nf_discover_search_result( OpenAPI_search_result_t *SearchResult); +/** + * Handles NF registration in NRF. Validates the PLMN-ID against configured + * serving PLMN-IDs and registers the NF instance if valid. + * + * @param nf_instance The NF instance being registered. + * @param stream The SBI stream for communication. + * @param recvmsg The received SBI message. + * @return true if registration is successful; otherwise, false. + */ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { @@ -33,6 +42,10 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance, OpenAPI_nf_profile_t *NFProfile = NULL; + OpenAPI_lnode_t *node = NULL; + bool plmn_valid = false; + int i; + ogs_assert(nf_instance); ogs_assert(stream); ogs_assert(recvmsg); @@ -73,6 +86,41 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance, return false; } + /* Validate the PLMN-ID against configured serving PLMN-IDs */ + if (NFProfile->plmn_list) { + /* Set PLMN status to invalid */ + plmn_valid = false; + + if (ogs_local_conf()->num_of_serving_plmn_id > 0 && NFProfile->plmn_list) { + OpenAPI_list_for_each(NFProfile->plmn_list, node) { + OpenAPI_plmn_id_t *PlmnId = node->data; + if (PlmnId == NULL) { + continue; + } + for (i = 0; i < ogs_local_conf()->num_of_serving_plmn_id; i++) { + if (ogs_sbi_compare_plmn_list( + &ogs_local_conf()->serving_plmn_id[i], + PlmnId) == true) { + plmn_valid = true; + break; + } + } + if (plmn_valid) { + break; + } + } + } + + /* Reject the registration if PLMN-ID is invalid */ + if (!plmn_valid) { + ogs_error("PLMN-ID in NFProfile is not allowed"); + ogs_assert(true == ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, + "PLMN-ID not allowed", NULL, NULL)); + return false; + } + } + ogs_nnrf_nfm_handle_nf_profile(nf_instance, NFProfile); ogs_sbi_client_associate(nf_instance); @@ -146,7 +194,6 @@ bool nrf_nnrf_handle_nf_register(ogs_sbi_nf_instance_t *nf_instance, if (ogs_local_conf()->num_of_serving_plmn_id && NFProfile->plmn_list == NULL) { OpenAPI_list_t *PlmnIdList = NULL; - int i; PlmnIdList = OpenAPI_list_create(); ogs_assert(PlmnIdList); @@ -208,6 +255,10 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance, ogs_assert(stream); ogs_assert(recvmsg); + cJSON *plmn_array = NULL, *plmn_item = NULL; + bool plmn_valid = false; + int i; + SWITCH(recvmsg->h.method) CASE(OGS_SBI_HTTP_METHOD_PUT) return nrf_nnrf_handle_nf_register( @@ -224,14 +275,14 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance, return false; } + /* Iterate through the PatchItemList */ OpenAPI_list_for_each(PatchItemList, node) { OpenAPI_patch_item_t *patch_item = node->data; if (!patch_item) { ogs_error("No PatchItem"); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - recvmsg, "No PatchItem", NULL, NULL)); + ogs_assert(true == ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, + "No PatchItem", NULL, NULL)); return false; } @@ -246,6 +297,102 @@ bool nrf_nnrf_handle_nf_update(ogs_sbi_nf_instance_t *nf_instance, break; CASE(OGS_SBI_PATCH_PATH_LOAD) break; + CASE(OGS_SBI_PATCH_PATH_PLMN_LIST) + /* Ensure the value is not null and is a valid JSON array */ + if (patch_item->value && patch_item->value->json) { + /* Set PLMN status to invalid */ + plmn_valid = false; + + plmn_array = patch_item->value->json; + if (!cJSON_IsArray(plmn_array)) { + ogs_error("Value for /plmnList is not a JSON array"); + ogs_assert(true == ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, + "Invalid value for /plmnList", NULL, NULL)); + return false; + } + + /* Clear existing PLMN data in nf_instance */ + memset(nf_instance->plmn_id, 0, + sizeof(nf_instance->plmn_id)); + nf_instance->num_of_plmn_id = 0; + + /* Iterate through the JSON array of PLMN IDs */ + cJSON_ArrayForEach(plmn_item, plmn_array) { + OpenAPI_plmn_id_t plmn_id; + memset(&plmn_id, 0, sizeof(plmn_id)); + + if (nf_instance->num_of_plmn_id >= + OGS_ARRAY_SIZE(nf_instance->plmn_id)) { + ogs_error("Exceeded maximum number of PLMN IDs"); + ogs_assert(true == ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, + "Too many PLMN IDs", NULL, NULL)); + return false; + } + + /* Parse the PLMN item */ + plmn_id.mcc = cJSON_GetObjectItem(plmn_item, "mcc") + ? cJSON_GetStringValue( + cJSON_GetObjectItem( + plmn_item, "mcc")) + : NULL; + plmn_id.mnc = cJSON_GetObjectItem(plmn_item, "mnc") + ? cJSON_GetStringValue( + cJSON_GetObjectItem( + plmn_item, "mnc")) + : NULL; + + if (!plmn_id.mcc || !plmn_id.mnc) { + ogs_error( + "Invalid PLMN item in /plmnList update"); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, + "Invalid PLMN item", NULL, + NULL)); + return false; + } + + /* + * Convert OpenAPI_plmn_id_t to ogs_plmn_id_t + * and store in nf_instance + */ + ogs_sbi_parse_plmn_id( + &nf_instance-> + plmn_id[nf_instance->num_of_plmn_id], + &plmn_id); + nf_instance->num_of_plmn_id++; + + /* Compare with the serving PLMN list */ + for (i = 0; + i < ogs_local_conf()->num_of_serving_plmn_id; + i++) { + if (ogs_sbi_compare_plmn_list( + &ogs_local_conf()->serving_plmn_id[i], + &plmn_id) == true) { + plmn_valid = true; + break; + } + } + if (plmn_valid) { + break; + } + } + + /* Reject the update if PLMN-ID is invalid */ + if (!plmn_valid) { + ogs_error("PLMN-ID in NFProfile update is not allowed"); + ogs_assert(true == ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, recvmsg, + "PLMN-ID not allowed", NULL, NULL)); + return false; + } + } + break; DEFAULT ogs_error("Unknown PatchItem.Path [%s]", patch_item->path); END @@ -386,6 +533,9 @@ bool nrf_nnrf_handle_nf_status_subscribe( else if (SubscrCond->service_name) subscription_data->subscr_cond.service_name = ogs_strdup(SubscrCond->service_name); + else if (SubscrCond->nf_instance_id) + subscription_data->subscr_cond.nf_instance_id = + ogs_strdup(SubscrCond->nf_instance_id); else { ogs_error("No SubscrCond"); ogs_sbi_subscription_data_remove(subscription_data); diff --git a/src/nrf/sbi-path.c b/src/nrf/sbi-path.c index 02c0b967e..303f5c866 100644 --- a/src/nrf/sbi-path.c +++ b/src/nrf/sbi-path.c @@ -127,6 +127,9 @@ bool nrf_nnrf_nfm_send_nf_status_notify_all( ogs_sbi_nf_service_is_allowed_nf_type( nf_service, subscription_data->req_nf_type) == false) continue; + } else if (subscription_data->subscr_cond.nf_instance_id) { + if (strcmp(subscription_data->subscr_cond.nf_instance_id, nf_instance->id) != 0) + continue; } if (subscription_data->req_nf_type && diff --git a/src/nssf/context.c b/src/nssf/context.c index 6382c37cd..b5b49d150 100644 --- a/src/nssf/context.c +++ b/src/nssf/context.c @@ -289,7 +289,6 @@ nssf_nsi_t *nssf_nsi_add(char *nrf_id, uint8_t sst, ogs_uint24_t sd) nssf_nsi_t *nsi = NULL; ogs_assert(nrf_id); - ogs_assert(sst); ogs_pool_alloc(&nssf_nsi_pool, &nsi); ogs_assert(nsi); diff --git a/src/pcf/context.c b/src/pcf/context.c index c90855357..41f1779bd 100644 --- a/src/pcf/context.c +++ b/src/pcf/context.c @@ -119,6 +119,7 @@ static int parse_slice_conf( do { ogs_app_slice_conf_t *slice_conf = NULL; ogs_s_nssai_t s_nssai; + bool sst_presence = false; bool default_indicator = false; s_nssai.sst = 0; @@ -131,13 +132,8 @@ static int parse_slice_conf( if (!strcmp(slice_key, OGS_SST_STRING)) { const char *v = ogs_yaml_iter_value(&slice_iter); if (v) { + sst_presence = true; s_nssai.sst = atoi(v); - if (s_nssai.sst == 1 || s_nssai.sst == 2 || - s_nssai.sst == 3 || s_nssai.sst == 4) { - } else { - ogs_error("Unknown SST [%d]", s_nssai.sst); - return OGS_ERROR; - } } } else if (!strcmp(slice_key, OGS_SD_STRING)) { const char *v = ogs_yaml_iter_value(&slice_iter); @@ -147,7 +143,7 @@ static int parse_slice_conf( } } - if (s_nssai.sst) { + if (sst_presence) { slice_conf = ogs_app_slice_conf_add(policy_conf, &s_nssai); if (!slice_conf) { ogs_error("ogs_app_slice_conf_add() failed [SST:%d,SD:0x%x]", diff --git a/src/pcf/nbsf-build.c b/src/pcf/nbsf-build.c index 81680eddb..0454b8df2 100644 --- a/src/pcf/nbsf-build.c +++ b/src/pcf/nbsf-build.c @@ -35,15 +35,14 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( ogs_sbi_nf_instance_t *nf_instance = NULL; ogs_sbi_nf_service_t *nf_service = NULL; + OpenAPI_nf_type_e requester_nf_type = OpenAPI_nf_type_NULL; + int i; ogs_assert(sess); pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); ogs_assert(pcf_ue); - nf_instance = data; - ogs_assert(nf_instance); - memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NBSF_MANAGEMENT; @@ -69,6 +68,13 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( } PcfBinding.dnn = sess->dnn; + requester_nf_type = NF_INSTANCE_TYPE(ogs_sbi_self()->nf_instance); + ogs_assert(requester_nf_type); + nf_instance = ogs_sbi_nf_instance_find_by_service_type( + OGS_SBI_SERVICE_TYPE_NPCF_POLICYAUTHORIZATION, + requester_nf_type); + ogs_assert(nf_instance); + nf_service = ogs_sbi_nf_service_find_by_name( nf_instance, (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION); if (!nf_service) { @@ -127,10 +133,6 @@ ogs_sbi_request_t *pcf_nbsf_management_build_register( } } - if (!sess->s_nssai.sst) { - ogs_error("No SST"); - goto end; - } if (PcfIpEndPointList->count) PcfBinding.pcf_ip_end_points = PcfIpEndPointList; else diff --git a/src/pcf/nbsf-handler.c b/src/pcf/nbsf-handler.c index 7cb5a28a9..14efee5e6 100644 --- a/src/pcf/nbsf-handler.c +++ b/src/pcf/nbsf-handler.c @@ -24,44 +24,16 @@ bool pcf_nbsf_management_handle_register( pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { - int i, rv, status = 0; + int rv, status = 0; char *strerror = NULL; pcf_ue_t *pcf_ue = NULL; ogs_sbi_server_t *server = NULL; - ogs_sbi_message_t sendmsg; ogs_sbi_header_t header; - ogs_sbi_response_t *response = NULL; - ogs_sbi_message_t message; - ogs_session_data_t session_data; - - ogs_session_t *session = NULL; - OpenAPI_pcf_binding_t *PcfBinding = NULL; - OpenAPI_sm_policy_decision_t SmPolicyDecision; - - OpenAPI_lnode_t *node = NULL; - - OpenAPI_list_t *SessRuleList = NULL; - OpenAPI_map_t *SessRuleMap = NULL; - OpenAPI_session_rule_t *SessionRule = NULL; - - OpenAPI_ambr_t AuthSessAmbr; - OpenAPI_authorized_default_qos_t AuthDefQos; - - OpenAPI_list_t *PccRuleList = NULL; - OpenAPI_map_t *PccRuleMap = NULL; - OpenAPI_pcc_rule_t *PccRule = NULL; - - OpenAPI_list_t *QosDecisionList = NULL; - OpenAPI_map_t *QosDecisionMap = NULL; - OpenAPI_qos_data_t *QosData = NULL; - - OpenAPI_list_t *PolicyCtrlReqTriggers = NULL; - bool rc; ogs_sbi_client_t *client = NULL; OpenAPI_uri_scheme_e scheme = OpenAPI_uri_scheme_NULL; @@ -78,8 +50,6 @@ bool pcf_nbsf_management_handle_register( ogs_assert(recvmsg); - memset(&session_data, 0, sizeof(ogs_session_data_t)); - ogs_assert(pcf_ue->supi); ogs_assert(sess->dnn); @@ -158,307 +128,33 @@ bool pcf_nbsf_management_handle_register( ogs_sbi_header_free(&header); - rv = pcf_db_qos_data( - pcf_ue->supi, - sess->home.presence == true ? &sess->home.plmn_id : NULL, - &sess->s_nssai, sess->dnn, &session_data); - if (rv != OGS_OK) { - strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", - pcf_ue->supi, sess->psi); - status = OGS_SBI_HTTP_STATUS_NOT_FOUND; - goto cleanup; - } + /* Send Response for SM Policy Association establishment */ + rc = pcf_sbi_send_smpolicycontrol_create_response(sess, stream); + ogs_expect(rc == true); - session = &session_data.session; - - if (!session->qos.index) { - strerror = ogs_msprintf("[%s:%d] No 5QI", pcf_ue->supi, sess->psi); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - } - if (!session->qos.arp.priority_level) { - strerror = ogs_msprintf("[%s:%d] No Priority Level", - pcf_ue->supi, sess->psi); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - } - - if (!session->ambr.uplink && !session->ambr.downlink) { - strerror = ogs_msprintf("[%s:%d] No Session-AMBR", - pcf_ue->supi, sess->psi); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - } - - memset(&SmPolicyDecision, 0, sizeof(SmPolicyDecision)); - - PolicyCtrlReqTriggers = OpenAPI_list_create(); - ogs_assert(PolicyCtrlReqTriggers); - - /************************************************************** - * Session Rule - *************************************************************/ - SessRuleList = OpenAPI_list_create(); - ogs_assert(SessRuleList); - - SessionRule = ogs_calloc(1, sizeof(*SessionRule)); - ogs_assert(SessionRule); - - /* Only 1 SessionRule is used */ - SessionRule->sess_rule_id = (char *)"1"; - - if (OGS_SBI_FEATURES_IS_SET(sess->smpolicycontrol_features, - OGS_SBI_NPCF_SMPOLICYCONTROL_DN_AUTHORIZATION)) { - if (sess->subscribed_sess_ambr) { - ogs_bitrate_t subscribed_sess_ambr; - - subscribed_sess_ambr.uplink = ogs_sbi_bitrate_from_string( - sess->subscribed_sess_ambr->uplink); - subscribed_sess_ambr.downlink = ogs_sbi_bitrate_from_string( - sess->subscribed_sess_ambr->downlink); - if (((subscribed_sess_ambr.uplink / 1000) != - (session->ambr.uplink / 1000)) || - ((subscribed_sess_ambr.downlink / 1000) != - (session->ambr.downlink / 1000))) { - - OpenAPI_list_add(PolicyCtrlReqTriggers, - (void *)OpenAPI_policy_control_request_trigger_SE_AMBR_CH); - } - - memset(&AuthSessAmbr, 0, sizeof(AuthSessAmbr)); - AuthSessAmbr.uplink = ogs_sbi_bitrate_to_string( - session->ambr.uplink, OGS_SBI_BITRATE_KBPS); - AuthSessAmbr.downlink = ogs_sbi_bitrate_to_string( - session->ambr.downlink, OGS_SBI_BITRATE_KBPS); - SessionRule->auth_sess_ambr = &AuthSessAmbr; - } - } - - if (sess->subscribed_default_qos) { - bool triggered = false; - - memset(&AuthDefQos, 0, sizeof(AuthDefQos)); - AuthDefQos.arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); - ogs_assert(AuthDefQos.arp); - - AuthDefQos.is__5qi = true; - AuthDefQos._5qi = session->qos.index; - AuthDefQos.is_priority_level = true; - AuthDefQos.priority_level = session->qos.arp.priority_level; - - if (session->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_ENABLED) - AuthDefQos.arp->preempt_cap = - OpenAPI_preemption_capability_MAY_PREEMPT; - else if (session->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_DISABLED) - AuthDefQos.arp->preempt_cap = - OpenAPI_preemption_capability_NOT_PREEMPT; - ogs_assert(AuthDefQos.arp->preempt_cap); - - if (session->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_ENABLED) - AuthDefQos.arp->preempt_vuln = - OpenAPI_preemption_vulnerability_PREEMPTABLE; - else if (session->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_DISABLED) - AuthDefQos.arp->preempt_vuln = - OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; - ogs_assert(AuthDefQos.arp->preempt_vuln); - AuthDefQos.arp->priority_level = session->qos.arp.priority_level; - - SessionRule->auth_def_qos = &AuthDefQos; - - if (sess->subscribed_default_qos->_5qi != AuthDefQos._5qi) - triggered = true; - if (sess->subscribed_default_qos->priority_level != - AuthDefQos.priority_level) - triggered = true; - if (sess->subscribed_default_qos->arp) { - if (sess->subscribed_default_qos->arp->priority_level != - AuthDefQos.arp->priority_level) - triggered = true; - if (sess->subscribed_default_qos->arp->preempt_cap != - AuthDefQos.arp->preempt_cap) - triggered = true; - if (sess->subscribed_default_qos->arp->preempt_vuln != - AuthDefQos.arp->preempt_vuln) - triggered = true; - - } - - if (triggered) - OpenAPI_list_add(PolicyCtrlReqTriggers, - (void *)OpenAPI_policy_control_request_trigger_DEF_QOS_CH); - - } - - SessRuleMap = OpenAPI_map_create( - SessionRule->sess_rule_id, SessionRule); - ogs_assert(SessRuleMap); - - OpenAPI_list_add(SessRuleList, SessRuleMap); - - if (SessRuleList->count) - SmPolicyDecision.sess_rules = SessRuleList; - - /************************************************************** - * PCC Rule & QoS Decision - *************************************************************/ - PccRuleList = OpenAPI_list_create(); - ogs_assert(PccRuleList); - - QosDecisionList = OpenAPI_list_create(); - ogs_assert(QosDecisionList); - - for (i = 0; i < session_data.num_of_pcc_rule; i++) { - ogs_pcc_rule_t *pcc_rule = &session_data.pcc_rule[i]; - - ogs_assert(pcc_rule); - ogs_assert(pcc_rule->id); - - if (!pcc_rule->num_of_flow) { - /* No Flow */ - continue; - } - - PccRule = ogs_sbi_build_pcc_rule(pcc_rule, 1); - ogs_assert(PccRule->pcc_rule_id); - - PccRuleMap = OpenAPI_map_create(PccRule->pcc_rule_id, PccRule); - ogs_assert(PccRuleMap); - - OpenAPI_list_add(PccRuleList, PccRuleMap); - - QosData = ogs_sbi_build_qos_data(pcc_rule); - ogs_assert(QosData); - ogs_assert(QosData->qos_id); - - QosDecisionMap = OpenAPI_map_create(QosData->qos_id, QosData); - ogs_assert(QosDecisionMap); - - OpenAPI_list_add(QosDecisionList, QosDecisionMap); - } - - if (PccRuleList->count) - SmPolicyDecision.pcc_rules = PccRuleList; - - if (QosDecisionList->count) - SmPolicyDecision.qos_decs = QosDecisionList; - - /* Policy Control Request Triggers */ - if (PolicyCtrlReqTriggers->count) - SmPolicyDecision.policy_ctrl_req_triggers = PolicyCtrlReqTriggers; - - /* Supported Features */ - if (sess->smpolicycontrol_features) { - SmPolicyDecision.supp_feat = - ogs_uint64_to_string(sess->smpolicycontrol_features); - ogs_assert(SmPolicyDecision.supp_feat); - } - - memset(&header, 0, sizeof(header)); - header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL; - header.api.version = (char *)OGS_SBI_API_V1; - header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_SM_POLICIES; - header.resource.component[1] = sess->sm_policy_id; - - memset(&sendmsg, 0, sizeof(sendmsg)); - sendmsg.SmPolicyDecision = &SmPolicyDecision; - sendmsg.http.location = ogs_sbi_server_uri(server, &header); - - response = ogs_sbi_build_response( - &sendmsg, OGS_SBI_HTTP_STATUS_CREATED); - ogs_assert(response); - ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - - ogs_free(sendmsg.http.location); - - OpenAPI_list_for_each(SessRuleList, node) { - SessRuleMap = node->data; - if (SessRuleMap) { - SessionRule = SessRuleMap->value; - if (SessionRule) { - if (SessionRule->auth_sess_ambr) { - if (SessionRule->auth_sess_ambr->uplink) - ogs_free(SessionRule->auth_sess_ambr->uplink); - if (SessionRule->auth_sess_ambr->downlink) - ogs_free(SessionRule->auth_sess_ambr->downlink); - } - if (SessionRule->auth_def_qos) { - ogs_free(SessionRule->auth_def_qos->arp); - - } - ogs_free(SessionRule); - } - ogs_free(SessRuleMap); - } - } - OpenAPI_list_free(SessRuleList); - - OpenAPI_list_for_each(PccRuleList, node) { - PccRuleMap = node->data; - if (PccRuleMap) { - PccRule = PccRuleMap->value; - if (PccRule) - ogs_sbi_free_pcc_rule(PccRule); - ogs_free(PccRuleMap); - } - } - OpenAPI_list_free(PccRuleList); - - OpenAPI_list_for_each(QosDecisionList, node) { - QosDecisionMap = node->data; - if (QosDecisionMap) { - QosData = QosDecisionMap->value; - if (QosData) - ogs_sbi_free_qos_data(QosData); - ogs_free(QosDecisionMap); - } - } - OpenAPI_list_free(QosDecisionList); - - OpenAPI_list_free(PolicyCtrlReqTriggers); - - if (SmPolicyDecision.supp_feat) - ogs_free(SmPolicyDecision.supp_feat); - - pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, - &sess->s_nssai, PCF_METR_CTR_PA_POLICYSMASSOSUCC, 1); - - OGS_SESSION_DATA_FREE(&session_data); - - return true; + return rc; cleanup: ogs_assert(strerror); ogs_assert(status); ogs_error("%s", strerror); - ogs_assert(true == - ogs_sbi_server_send_error(stream, status, recvmsg, strerror, NULL, - NULL)); + ogs_assert(true == ogs_sbi_server_send_error( + stream, status, recvmsg, strerror, NULL, NULL)); ogs_free(strerror); - OGS_SESSION_DATA_FREE(&session_data); - return false; } bool pcf_nbsf_management_handle_de_register( pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { - ogs_sbi_message_t sendmsg; - ogs_sbi_response_t *response = NULL; + bool rc; ogs_assert(sess); ogs_assert(stream); - memset(&sendmsg, 0, sizeof(sendmsg)); + rc = ogs_sbi_send_response(stream, OGS_SBI_HTTP_STATUS_NO_CONTENT); + ogs_expect(rc == true); - response = ogs_sbi_build_response( - &sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); - ogs_assert(response); - ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - - return true; + return rc; } diff --git a/src/pcf/nnrf-handler.c b/src/pcf/nnrf-handler.c index ca5d6ea66..4a3247580 100644 --- a/src/pcf/nnrf-handler.c +++ b/src/pcf/nnrf-handler.c @@ -23,13 +23,11 @@ void pcf_nnrf_handle_nf_discover( ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg) { - int r; ogs_sbi_nf_instance_t *nf_instance = NULL; ogs_sbi_object_t *sbi_object = NULL; ogs_pool_id_t sbi_object_id = OGS_INVALID_POOL_ID; ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL; ogs_sbi_discovery_option_t *discovery_option = NULL; - ogs_sbi_stream_t *stream = NULL; pcf_ue_t *pcf_ue = NULL; pcf_sess_t *sess = NULL; @@ -55,10 +53,6 @@ void pcf_nnrf_handle_nf_discover( discovery_option = xact->discovery_option; - if (xact->assoc_stream_id >= OGS_MIN_POOL_ID && - xact->assoc_stream_id <= OGS_MAX_POOL_ID) - stream = ogs_sbi_stream_find_by_id(xact->assoc_stream_id); - SearchResult = recvmsg->SearchResult; if (!SearchResult) { ogs_error("No SearchResult"); @@ -89,28 +83,28 @@ void pcf_nnrf_handle_nf_discover( sess ? sess->psi : 0, ogs_sbi_service_type_to_name(service_type), OpenAPI_nf_type_ToString(requester_nf_type)); + + /* If BSF is not reachable, we ignore NBSF_MANAGMENT service */ + if (service_type == OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT) { + ogs_sbi_stream_t *stream = NULL; + + ogs_assert(xact->assoc_stream_id >= OGS_MIN_POOL_ID && + xact->assoc_stream_id <= OGS_MAX_POOL_ID); + stream = ogs_sbi_stream_find_by_id(xact->assoc_stream_id); + ogs_assert(stream); + + /* Send Response for SM Policy Association establishment */ + ogs_expect(true == + pcf_sbi_send_smpolicycontrol_create_response(sess, stream)); + + ogs_sbi_xact_remove(xact); + } return; } OGS_SBI_SETUP_NF_INSTANCE( sbi_object->service_type_array[service_type], nf_instance); - switch (service_type) { - case OGS_SBI_SERVICE_TYPE_NPCF_POLICYAUTHORIZATION: - ogs_sbi_xact_remove(xact); - - ogs_assert(sess); - ogs_assert(stream); - r = pcf_sess_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, - pcf_nbsf_management_build_register, - sess, stream, nf_instance); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - break; - default: - ogs_assert(xact->request); - ogs_expect(true == pcf_sbi_send_request(nf_instance, xact)); - break; - } + ogs_assert(xact->request); + ogs_expect(true == pcf_sbi_send_request(nf_instance, xact)); } diff --git a/src/pcf/npcf-handler.c b/src/pcf/npcf-handler.c index 845fcdd7a..dadbdf273 100644 --- a/src/pcf/npcf-handler.c +++ b/src/pcf/npcf-handler.c @@ -299,13 +299,6 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, goto cleanup; } - if (!sliceInfo->sst) { - strerror = ogs_msprintf("[%s:%d] No sliceInfo->sst", - pcf_ue->supi, sess->psi); - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - goto cleanup; - } - servingNetwork = SmPolicyContextData->serving_network; if (servingNetwork) { if (!servingNetwork->mcc) { @@ -500,37 +493,12 @@ bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, if (ogs_sbi_supi_in_vplmn(pcf_ue->supi) == true) { /* Visited PLMN */ - ogs_sbi_nf_instance_t *nf_instance = NULL; - ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL; - - service_type = OGS_SBI_SERVICE_TYPE_NPCF_POLICYAUTHORIZATION; - - nf_instance = OGS_SBI_GET_NF_INSTANCE( - sess->sbi.service_type_array[service_type]); - if (!nf_instance) { - OpenAPI_nf_type_e requester_nf_type = - NF_INSTANCE_TYPE(ogs_sbi_self()->nf_instance); - ogs_assert(requester_nf_type); - nf_instance = ogs_sbi_nf_instance_find_by_service_type( - service_type, requester_nf_type); - if (nf_instance) - OGS_SBI_SETUP_NF_INSTANCE( - sess->sbi.service_type_array[service_type], - nf_instance); - } - - if (nf_instance) { - r = pcf_sess_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, - pcf_nbsf_management_build_register, - sess, stream, nf_instance); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - } else { - r = pcf_sess_sbi_discover_only(sess, stream, service_type); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - } + r = pcf_sess_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, + pcf_nbsf_management_build_register, + sess, stream, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); return (r == OGS_OK); } else { @@ -598,19 +566,17 @@ bool pcf_npcf_smpolicycontrol_handle_delete(pcf_sess_t *sess, if (pcf_sessions_number_by_snssai_and_dnn( pcf_ue, &sess->s_nssai, sess->dnn) > 1) { - ogs_sbi_message_t sendmsg; - memset(&sendmsg, 0, sizeof(sendmsg)); - - ogs_sbi_response_t *response = ogs_sbi_build_response( - &sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); - ogs_assert(response); - ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - } else { + ogs_expect(true == + ogs_sbi_send_response(stream, OGS_SBI_HTTP_STATUS_NO_CONTENT)); + } else if (sess->binding.resource_uri) { r = pcf_sess_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, pcf_nbsf_management_build_de_register, sess, stream, NULL); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); + } else { + ogs_expect(true == + ogs_sbi_send_response(stream, OGS_SBI_HTTP_STATUS_NO_CONTENT)); } return true; diff --git a/src/pcf/nudr-handler.c b/src/pcf/nudr-handler.c index 16d724ae9..be9c691b2 100644 --- a/src/pcf/nudr-handler.c +++ b/src/pcf/nudr-handler.c @@ -203,9 +203,6 @@ bool pcf_nudr_dr_handle_query_sm_data( SWITCH(recvmsg->h.resource.component[3]) CASE(OGS_SBI_RESOURCE_NAME_SM_DATA) - ogs_sbi_nf_instance_t *nf_instance = NULL; - ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL; - if (!recvmsg->SmPolicyData) { strerror = ogs_msprintf("[%s:%d] No SmPolicyData", pcf_ue->supi, sess->psi); @@ -213,34 +210,12 @@ bool pcf_nudr_dr_handle_query_sm_data( goto cleanup; } - service_type = OGS_SBI_SERVICE_TYPE_NPCF_POLICYAUTHORIZATION; - - nf_instance = OGS_SBI_GET_NF_INSTANCE( - sess->sbi.service_type_array[service_type]); - if (!nf_instance) { - OpenAPI_nf_type_e requester_nf_type = - NF_INSTANCE_TYPE(ogs_sbi_self()->nf_instance); - ogs_assert(requester_nf_type); - nf_instance = ogs_sbi_nf_instance_find_by_service_type( - service_type, requester_nf_type); - if (nf_instance) - OGS_SBI_SETUP_NF_INSTANCE( - sess->sbi.service_type_array[service_type], - nf_instance); - } - - if (nf_instance) { - r = pcf_sess_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, - pcf_nbsf_management_build_register, - sess, stream, nf_instance); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - } else { - r = pcf_sess_sbi_discover_only(sess, stream, service_type); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - } + r = pcf_sess_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NBSF_MANAGEMENT, NULL, + pcf_nbsf_management_build_register, + sess, stream, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); return true; diff --git a/src/pcf/sbi-path.c b/src/pcf/sbi-path.c index fe18a4026..4d358e45e 100644 --- a/src/pcf/sbi-path.c +++ b/src/pcf/sbi-path.c @@ -189,31 +189,6 @@ int pcf_ue_sbi_discover_and_send( return OGS_OK; } -int pcf_sess_sbi_discover_only( - pcf_sess_t *sess, ogs_sbi_stream_t *stream, - ogs_sbi_service_type_e service_type) -{ - ogs_sbi_xact_t *xact = NULL; - - ogs_assert(sess); - ogs_assert(service_type); - - xact = ogs_sbi_xact_add( - 0, &sess->sbi, service_type, NULL, NULL, NULL, NULL); - if (!xact) { - ogs_error("ogs_sbi_xact_add() failed"); - return OGS_ERROR; - } - - if (stream) { - xact->assoc_stream_id = ogs_sbi_id_from_stream(stream); - ogs_assert(xact->assoc_stream_id >= OGS_MIN_POOL_ID && - xact->assoc_stream_id <= OGS_MAX_POOL_ID); - } - - return ogs_sbi_discover_only(xact); -} - int pcf_sess_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option, @@ -307,6 +282,340 @@ bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue) return rc; } +bool pcf_sbi_send_smpolicycontrol_create_response( + pcf_sess_t *sess, ogs_sbi_stream_t *stream) +{ + int i, rv, status = 0; + char *strerror = NULL; + pcf_ue_t *pcf_ue = NULL; + ogs_sbi_server_t *server = NULL; + + ogs_sbi_message_t sendmsg; + ogs_sbi_header_t header; + ogs_sbi_response_t *response = NULL; + + ogs_session_data_t session_data; + + ogs_session_t *session = NULL; + + OpenAPI_sm_policy_decision_t SmPolicyDecision; + + OpenAPI_lnode_t *node = NULL; + + OpenAPI_list_t *SessRuleList = NULL; + OpenAPI_map_t *SessRuleMap = NULL; + OpenAPI_session_rule_t *SessionRule = NULL; + + OpenAPI_ambr_t AuthSessAmbr; + OpenAPI_authorized_default_qos_t AuthDefQos; + + OpenAPI_list_t *PccRuleList = NULL; + OpenAPI_map_t *PccRuleMap = NULL; + OpenAPI_pcc_rule_t *PccRule = NULL; + + OpenAPI_list_t *QosDecisionList = NULL; + OpenAPI_map_t *QosDecisionMap = NULL; + OpenAPI_qos_data_t *QosData = NULL; + + OpenAPI_list_t *PolicyCtrlReqTriggers = NULL; + + ogs_assert(sess); + pcf_ue = pcf_ue_find_by_id(sess->pcf_ue_id); + ogs_assert(pcf_ue); + ogs_assert(stream); + server = ogs_sbi_server_from_stream(stream); + ogs_assert(server); + + memset(&session_data, 0, sizeof(ogs_session_data_t)); + + ogs_assert(pcf_ue->supi); + ogs_assert(sess->dnn); + + rv = pcf_db_qos_data( + pcf_ue->supi, + sess->home.presence == true ? &sess->home.plmn_id : NULL, + &sess->s_nssai, sess->dnn, &session_data); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_NOT_FOUND; + goto cleanup; + } + + session = &session_data.session; + + if (!session->qos.index) { + strerror = ogs_msprintf("[%s:%d] No 5QI", pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + if (!session->qos.arp.priority_level) { + strerror = ogs_msprintf("[%s:%d] No Priority Level", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + + if (!session->ambr.uplink && !session->ambr.downlink) { + strerror = ogs_msprintf("[%s:%d] No Session-AMBR", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + + memset(&SmPolicyDecision, 0, sizeof(SmPolicyDecision)); + + PolicyCtrlReqTriggers = OpenAPI_list_create(); + ogs_assert(PolicyCtrlReqTriggers); + + /************************************************************** + * Session Rule + *************************************************************/ + SessRuleList = OpenAPI_list_create(); + ogs_assert(SessRuleList); + + SessionRule = ogs_calloc(1, sizeof(*SessionRule)); + ogs_assert(SessionRule); + + /* Only 1 SessionRule is used */ + SessionRule->sess_rule_id = (char *)"1"; + + if (OGS_SBI_FEATURES_IS_SET(sess->smpolicycontrol_features, + OGS_SBI_NPCF_SMPOLICYCONTROL_DN_AUTHORIZATION)) { + if (sess->subscribed_sess_ambr) { + ogs_bitrate_t subscribed_sess_ambr; + + subscribed_sess_ambr.uplink = ogs_sbi_bitrate_from_string( + sess->subscribed_sess_ambr->uplink); + subscribed_sess_ambr.downlink = ogs_sbi_bitrate_from_string( + sess->subscribed_sess_ambr->downlink); + if (((subscribed_sess_ambr.uplink / 1000) != + (session->ambr.uplink / 1000)) || + ((subscribed_sess_ambr.downlink / 1000) != + (session->ambr.downlink / 1000))) { + + OpenAPI_list_add(PolicyCtrlReqTriggers, + (void *)OpenAPI_policy_control_request_trigger_SE_AMBR_CH); + } + + memset(&AuthSessAmbr, 0, sizeof(AuthSessAmbr)); + AuthSessAmbr.uplink = ogs_sbi_bitrate_to_string( + session->ambr.uplink, OGS_SBI_BITRATE_KBPS); + AuthSessAmbr.downlink = ogs_sbi_bitrate_to_string( + session->ambr.downlink, OGS_SBI_BITRATE_KBPS); + SessionRule->auth_sess_ambr = &AuthSessAmbr; + } + } + + if (sess->subscribed_default_qos) { + bool triggered = false; + + memset(&AuthDefQos, 0, sizeof(AuthDefQos)); + AuthDefQos.arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); + ogs_assert(AuthDefQos.arp); + + AuthDefQos.is__5qi = true; + AuthDefQos._5qi = session->qos.index; + AuthDefQos.is_priority_level = true; + AuthDefQos.priority_level = session->qos.arp.priority_level; + + if (session->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_ENABLED) + AuthDefQos.arp->preempt_cap = + OpenAPI_preemption_capability_MAY_PREEMPT; + else if (session->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_DISABLED) + AuthDefQos.arp->preempt_cap = + OpenAPI_preemption_capability_NOT_PREEMPT; + ogs_assert(AuthDefQos.arp->preempt_cap); + + if (session->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_ENABLED) + AuthDefQos.arp->preempt_vuln = + OpenAPI_preemption_vulnerability_PREEMPTABLE; + else if (session->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_DISABLED) + AuthDefQos.arp->preempt_vuln = + OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; + ogs_assert(AuthDefQos.arp->preempt_vuln); + AuthDefQos.arp->priority_level = session->qos.arp.priority_level; + + SessionRule->auth_def_qos = &AuthDefQos; + + if (sess->subscribed_default_qos->_5qi != AuthDefQos._5qi) + triggered = true; + if (sess->subscribed_default_qos->priority_level != + AuthDefQos.priority_level) + triggered = true; + if (sess->subscribed_default_qos->arp) { + if (sess->subscribed_default_qos->arp->priority_level != + AuthDefQos.arp->priority_level) + triggered = true; + if (sess->subscribed_default_qos->arp->preempt_cap != + AuthDefQos.arp->preempt_cap) + triggered = true; + if (sess->subscribed_default_qos->arp->preempt_vuln != + AuthDefQos.arp->preempt_vuln) + triggered = true; + + } + + if (triggered) + OpenAPI_list_add(PolicyCtrlReqTriggers, + (void *)OpenAPI_policy_control_request_trigger_DEF_QOS_CH); + + } + + SessRuleMap = OpenAPI_map_create( + SessionRule->sess_rule_id, SessionRule); + ogs_assert(SessRuleMap); + + OpenAPI_list_add(SessRuleList, SessRuleMap); + + if (SessRuleList->count) + SmPolicyDecision.sess_rules = SessRuleList; + + /************************************************************** + * PCC Rule & QoS Decision + *************************************************************/ + PccRuleList = OpenAPI_list_create(); + ogs_assert(PccRuleList); + + QosDecisionList = OpenAPI_list_create(); + ogs_assert(QosDecisionList); + + for (i = 0; i < session_data.num_of_pcc_rule; i++) { + ogs_pcc_rule_t *pcc_rule = &session_data.pcc_rule[i]; + + ogs_assert(pcc_rule); + ogs_assert(pcc_rule->id); + + if (!pcc_rule->num_of_flow) { + /* No Flow */ + continue; + } + + PccRule = ogs_sbi_build_pcc_rule(pcc_rule, 1); + ogs_assert(PccRule->pcc_rule_id); + + PccRuleMap = OpenAPI_map_create(PccRule->pcc_rule_id, PccRule); + ogs_assert(PccRuleMap); + + OpenAPI_list_add(PccRuleList, PccRuleMap); + + QosData = ogs_sbi_build_qos_data(pcc_rule); + ogs_assert(QosData); + ogs_assert(QosData->qos_id); + + QosDecisionMap = OpenAPI_map_create(QosData->qos_id, QosData); + ogs_assert(QosDecisionMap); + + OpenAPI_list_add(QosDecisionList, QosDecisionMap); + } + + if (PccRuleList->count) + SmPolicyDecision.pcc_rules = PccRuleList; + + if (QosDecisionList->count) + SmPolicyDecision.qos_decs = QosDecisionList; + + /* Policy Control Request Triggers */ + if (PolicyCtrlReqTriggers->count) + SmPolicyDecision.policy_ctrl_req_triggers = PolicyCtrlReqTriggers; + + /* Supported Features */ + if (sess->smpolicycontrol_features) { + SmPolicyDecision.supp_feat = + ogs_uint64_to_string(sess->smpolicycontrol_features); + ogs_assert(SmPolicyDecision.supp_feat); + } + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_SM_POLICIES; + header.resource.component[1] = sess->sm_policy_id; + + memset(&sendmsg, 0, sizeof(sendmsg)); + sendmsg.SmPolicyDecision = &SmPolicyDecision; + sendmsg.http.location = ogs_sbi_server_uri(server, &header); + + response = ogs_sbi_build_response( + &sendmsg, OGS_SBI_HTTP_STATUS_CREATED); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + + ogs_free(sendmsg.http.location); + + OpenAPI_list_for_each(SessRuleList, node) { + SessRuleMap = node->data; + if (SessRuleMap) { + SessionRule = SessRuleMap->value; + if (SessionRule) { + if (SessionRule->auth_sess_ambr) { + if (SessionRule->auth_sess_ambr->uplink) + ogs_free(SessionRule->auth_sess_ambr->uplink); + if (SessionRule->auth_sess_ambr->downlink) + ogs_free(SessionRule->auth_sess_ambr->downlink); + } + if (SessionRule->auth_def_qos) { + ogs_free(SessionRule->auth_def_qos->arp); + + } + ogs_free(SessionRule); + } + ogs_free(SessRuleMap); + } + } + OpenAPI_list_free(SessRuleList); + + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + PccRule = PccRuleMap->value; + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + QosData = QosDecisionMap->value; + if (QosData) + ogs_sbi_free_qos_data(QosData); + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); + + OpenAPI_list_free(PolicyCtrlReqTriggers); + + if (SmPolicyDecision.supp_feat) + ogs_free(SmPolicyDecision.supp_feat); + + pcf_metrics_inst_by_slice_add(&pcf_ue->guami.plmn_id, + &sess->s_nssai, PCF_METR_CTR_PA_POLICYSMASSOSUCC, 1); + + OGS_SESSION_DATA_FREE(&session_data); + + return true; + +cleanup: + ogs_assert(strerror); + ogs_assert(status); + ogs_error("%s", strerror); + ogs_assert(true == ogs_sbi_server_send_error( + stream, status, NULL, strerror, NULL, NULL)); + ogs_free(strerror); + + OGS_SESSION_DATA_FREE(&session_data); + + return false; +} + bool pcf_sbi_send_smpolicycontrol_update_notify( pcf_sess_t *sess, OpenAPI_sm_policy_decision_t *SmPolicyDecision) { diff --git a/src/pcf/sbi-path.h b/src/pcf/sbi-path.h index 069921244..b72465964 100644 --- a/src/pcf/sbi-path.h +++ b/src/pcf/sbi-path.h @@ -45,11 +45,10 @@ int pcf_sess_sbi_discover_and_send( ogs_sbi_discovery_option_t *discovery_option, ogs_sbi_request_t *(*build)(pcf_sess_t *sess, void *data), pcf_sess_t *sess, ogs_sbi_stream_t *stream, void *data); -int pcf_sess_sbi_discover_only( - pcf_sess_t *sess, ogs_sbi_stream_t *stream, - ogs_sbi_service_type_e service_type); bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue); +bool pcf_sbi_send_smpolicycontrol_create_response( + pcf_sess_t *sess, ogs_sbi_stream_t *stream); bool pcf_sbi_send_smpolicycontrol_update_notify( pcf_sess_t *sess, OpenAPI_sm_policy_decision_t *SmPolicyDecision); bool pcf_sbi_send_smpolicycontrol_delete_notify( diff --git a/src/pcf/sm-sm.c b/src/pcf/sm-sm.c index edd0f07fa..1693c1af8 100644 --- a/src/pcf/sm-sm.c +++ b/src/pcf/sm-sm.c @@ -291,8 +291,22 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) } else { SWITCH(message->h.method) CASE(OGS_SBI_HTTP_METHOD_POST) - pcf_nbsf_management_handle_register( - sess, stream, message); + if (message->res_status == + OGS_SBI_HTTP_STATUS_CREATED) { + pcf_nbsf_management_handle_register( + sess, stream, message); + } else { + ogs_error("[%s:%d] HTTP response error [%d]", + pcf_ue->supi, sess->psi, message->res_status); + + /* + * Send Response + * for SM Policy Association establishment + */ + ogs_expect(true == + pcf_sbi_send_smpolicycontrol_create_response( + sess, stream)); + } break; DEFAULT ogs_error("[%s:%d] Unknown method [%s]", diff --git a/src/scp/sbi-path.c b/src/scp/sbi-path.c index 6f098cd1c..6e91aedf5 100644 --- a/src/scp/sbi-path.c +++ b/src/scp/sbi-path.c @@ -68,11 +68,11 @@ int scp_sbi_open(void) } /* Check if Next-SCP's client */ - if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_AUTO) { + if (ogs_sbi_self()->client_delegated_config.scp.next == + OGS_SBI_CLIENT_DELEGATED_AUTO) { next_scp = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); - } else if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_YES) { + } else if (ogs_sbi_self()->client_delegated_config.scp.next == + OGS_SBI_CLIENT_DELEGATED_YES) { next_scp = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); ogs_assert(next_scp); } @@ -153,11 +153,11 @@ static int request_handler(ogs_sbi_request_t *request, void *data) } /* Next-SCP client */ - if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_AUTO) { + if (ogs_sbi_self()->client_delegated_config.scp.next == + OGS_SBI_CLIENT_DELEGATED_AUTO) { next_scp = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); - } else if (ogs_sbi_self()->discovery_config.delegated == - OGS_SBI_DISCOVERY_DELEGATED_YES) { + } else if (ogs_sbi_self()->client_delegated_config.scp.next == + OGS_SBI_CLIENT_DELEGATED_YES) { next_scp = NF_INSTANCE_CLIENT(ogs_sbi_self()->scp_instance); ogs_assert(next_scp); } @@ -586,16 +586,6 @@ static int request_handler(ogs_sbi_request_t *request, void *data) return OGS_ERROR; } - assoc->request = request; - ogs_assert(assoc->request); - assoc->service_type = service_type; - ogs_assert(assoc->service_type); - - assoc->target_nf_type = target_nf_type; - ogs_assert(assoc->target_nf_type); - assoc->requester_nf_type = requester_nf_type; - ogs_assert(assoc->requester_nf_type); - if (!discovery_option->num_of_service_names) { ogs_error("No service names"); scp_assoc_remove(assoc); @@ -626,6 +616,16 @@ static int request_handler(ogs_sbi_request_t *request, void *data) "in TS29.500"); } + assoc->request = request; + ogs_assert(assoc->request); + assoc->service_type = service_type; + ogs_assert(assoc->service_type); + + assoc->target_nf_type = target_nf_type; + ogs_assert(assoc->target_nf_type); + assoc->requester_nf_type = requester_nf_type; + ogs_assert(assoc->requester_nf_type); + if (false == send_discover(nrf_client, nf_discover_handler, assoc)) { ogs_error("send_discover() failed"); scp_assoc_remove(assoc); @@ -717,7 +717,7 @@ static int response_handler( static int nf_discover_handler( int status, ogs_sbi_response_t *response, void *data) { - int rv; + int rv, res_status; char *strerror = NULL; ogs_sbi_message_t message; @@ -777,16 +777,19 @@ static int nf_discover_handler( rv = ogs_sbi_parse_response(&message, response); if (rv != OGS_OK) { strerror = ogs_msprintf("cannot parse HTTP response"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (message.res_status != OGS_SBI_HTTP_STATUS_OK) { strerror = ogs_msprintf("NF-Discover failed [%d]", message.res_status); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!message.SearchResult) { strerror = ogs_msprintf("No SearchResult"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -798,7 +801,7 @@ static int nf_discover_handler( strerror = ogs_msprintf("(NF discover) No NF-Instance [%s:%s]", ogs_sbi_service_type_to_name(service_type), OpenAPI_nf_type_ToString(requester_nf_type)); - + res_status = OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT; goto cleanup; } @@ -811,7 +814,7 @@ static int nf_discover_handler( strerror = ogs_msprintf("(NF discover) No client [%s:%s]", ogs_sbi_service_type_to_name(service_type), OpenAPI_nf_type_ToString(requester_nf_type)); - + res_status = OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT; goto cleanup; } @@ -825,6 +828,7 @@ static int nf_discover_handler( if (!sepp_client) { ogs_error("No SEPP [%s]", client->fqdn); strerror = ogs_msprintf("No SEPP [%s]", client->fqdn); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -839,6 +843,7 @@ static int nf_discover_handler( if (false == send_request( client, response_handler, request, false, assoc)) { strerror = ogs_msprintf("send_request() failed"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -854,10 +859,8 @@ cleanup: scp_assoc_remove(assoc); if (stream) { - ogs_assert(true == - ogs_sbi_server_send_error( - stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL, - NULL)); + ogs_assert(true == ogs_sbi_server_send_error( + stream, res_status, NULL, strerror, NULL, NULL)); } else ogs_error("STREAM has already been removed [%d]", stream_id); @@ -872,7 +875,7 @@ cleanup: static int sepp_discover_handler( int status, ogs_sbi_response_t *response, void *data) { - int rv; + int rv, res_status; char *strerror = NULL; ogs_sbi_message_t message; @@ -914,16 +917,19 @@ static int sepp_discover_handler( rv = ogs_sbi_parse_response(&message, response); if (rv != OGS_OK) { strerror = ogs_msprintf("cannot parse HTTP response"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (message.res_status != OGS_SBI_HTTP_STATUS_OK) { strerror = ogs_msprintf("NF-Discover failed [%d]", message.res_status); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } if (!message.SearchResult) { strerror = ogs_msprintf("No SearchResult"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -935,6 +941,7 @@ static int sepp_discover_handler( sepp_client = NF_INSTANCE_CLIENT(ogs_sbi_self()->sepp_instance); if (!sepp_client) { strerror = ogs_msprintf("No SEPP"); + res_status = OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT; goto cleanup; } @@ -945,6 +952,7 @@ static int sepp_discover_handler( if (false == send_request( sepp_client, response_handler, request, false, assoc)) { strerror = ogs_msprintf("send_request() failed"); + res_status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -960,10 +968,8 @@ cleanup: scp_assoc_remove(assoc); if (stream) { - ogs_assert(true == - ogs_sbi_server_send_error( - stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL, - NULL)); + ogs_assert(true == ogs_sbi_server_send_error( + stream, res_status, NULL, strerror, NULL, NULL)); } else ogs_error("STREAM has already been removed [%d]", stream_id); diff --git a/src/sgwc/context.c b/src/sgwc/context.c index 3c19ad7be..758486ef7 100644 --- a/src/sgwc/context.c +++ b/src/sgwc/context.c @@ -408,8 +408,6 @@ static ogs_pfcp_node_t *selected_sgwu_node( void sgwc_sess_select_sgwu(sgwc_sess_t *sess) { - char buf[OGS_ADDRSTRLEN]; - ogs_assert(sess); /* @@ -425,8 +423,9 @@ void sgwc_sess_select_sgwu(sgwc_sess_t *sess) selected_sgwu_node(ogs_pfcp_self()->pfcp_node, sess); ogs_assert(ogs_pfcp_self()->pfcp_node); OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->pfcp_node); - ogs_debug("UE using SGW-U on IP[%s]", - OGS_ADDR(&ogs_pfcp_self()->pfcp_node->addr, buf)); + ogs_debug("UE using SGW-U on IP %s", + ogs_sockaddr_to_string_static( + ogs_pfcp_self()->pfcp_node->addr_list)); } int sgwc_sess_remove(sgwc_sess_t *sess) @@ -761,14 +760,15 @@ sgwc_tunnel_t *sgwc_tunnel_add( else tunnel->local_teid = pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &tunnel->local_addr, &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + &tunnel->local_addr, sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &tunnel->local_addr6, &sess->pfcp_node->addr)); + &tunnel->local_addr6, sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index b0b12aadd..5712fa98c 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -61,8 +61,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; ogs_pfcp_node_t *node = NULL; + ogs_pfcp_message_t *message = NULL; ogs_pfcp_header_t *h = NULL; + ogs_pfcp_status_e pfcp_status;; + ogs_pfcp_node_id_t node_id; + ogs_assert(fd != INVALID_SOCKET); pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); @@ -102,28 +106,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) e = sgwc_event_new(SGWC_EVT_SXA_MESSAGE); ogs_assert(e); - node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - ogs_error("No memory: ogs_pfcp_node_add() failed"); - ogs_pkbuf_free(e->pkbuf); - sgwc_event_free(e); - return; - } - - node->sock = data; - pfcp_node_fsm_init(node, false); + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) { + ogs_error("ogs_pfcp_parse_msg() failed"); + ogs_pkbuf_free(pkbuf); + sgwc_event_free(e); + return; } + + pfcp_status = ogs_pfcp_extract_node_id(message, &node_id); + switch (pfcp_status) { + case OGS_PFCP_STATUS_SUCCESS: + case OGS_PFCP_STATUS_NODE_ID_NONE: + case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT: + ogs_debug("ogs_pfcp_extract_node_id() " + "type [%d] pfcp_status [%d] node_id [%s] from %s", + message->h.type, pfcp_status, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + break; + + case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE: + case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT: + case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND: + case OGS_PFCP_ERROR_UNKNOWN_MESSAGE: + ogs_error("ogs_pfcp_extract_node_id() failed " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + + default: + ogs_error("Unexpected pfcp_status " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + + node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from); + if (!node) { + if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE || + message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) { + ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS); + node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, + &node_id, &from); + if (!node) { + ogs_error("No memory: ogs_pfcp_node_add() failed"); + goto cleanup; + } + ogs_debug("Added PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + + pfcp_node_fsm_init(node, false); + + } else { + ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s", + message->h.type, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + } else { + ogs_debug("Found PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + ogs_expect(OGS_OK == ogs_pfcp_node_merge( + node, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, + &from)); + ogs_debug("Merged PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + } + e->pfcp_node = node; e->pkbuf = pkbuf; + e->pfcp_message = message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); - ogs_pkbuf_free(e->pkbuf); - sgwc_event_free(e); + goto cleanup; } + + return; + +cleanup: + ogs_pkbuf_free(pkbuf); + ogs_pfcp_message_free(message); + sgwc_event_free(e); } int sgwc_pfcp_open(void) diff --git a/src/sgwc/pfcp-sm.c b/src/sgwc/pfcp-sm.c index e0357ae61..bf9ed5aa2 100644 --- a/src/sgwc/pfcp-sm.c +++ b/src/sgwc/pfcp-sm.c @@ -25,7 +25,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data); void sgwc_pfcp_state_initial(ogs_fsm_t *s, sgwc_event_t *e) { - int rv; ogs_pfcp_node_t *node = NULL; ogs_assert(s); @@ -36,10 +35,6 @@ void sgwc_pfcp_state_initial(ogs_fsm_t *s, sgwc_event_t *e) node = e->pfcp_node; ogs_assert(node); - rv = ogs_pfcp_connect( - ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node); - ogs_assert(rv == OGS_OK); - node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, sgwc_timer_pfcp_no_heartbeat, node); ogs_assert(node->t_no_heartbeat); @@ -63,14 +58,10 @@ void sgwc_pfcp_state_final(ogs_fsm_t *s, sgwc_event_t *e) void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; - ogs_assert(s); ogs_assert(e); @@ -78,8 +69,6 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->id) { case OGS_FSM_ENTRY_SIG: @@ -103,8 +92,8 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e) node = e->pfcp_node; ogs_assert(node); - ogs_warn("Retry association with peer [%s]:%d failed", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("Retry association with peer failed %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_assert(node->t_association); ogs_timer_start(node->t_association, @@ -159,13 +148,10 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e) void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; sgwc_sess_t *sess = NULL; ogs_assert(s); @@ -175,14 +161,11 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->id) { case OGS_FSM_ENTRY_SIG: - ogs_info("PFCP associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_start(node->t_no_heartbeat, ogs_local_conf()->time.message.pfcp.no_heartbeat_duration); ogs_assert(OGS_OK == @@ -195,9 +178,8 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) } break; case OGS_FSM_EXIT_SIG: - ogs_info("PFCP de-associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP de-associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_stop(node->t_no_heartbeat); break; case SGWC_EVT_SXA_MESSAGE: @@ -274,16 +256,14 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) } break; case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: - ogs_warn("PFCP[REQ] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[REQ] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_cp_handle_association_setup_request(node, xact, &message->pfcp_association_setup_request); break; case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: - ogs_warn("PFCP[RSP] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[RSP] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_cp_handle_association_setup_response(node, xact, &message->pfcp_association_setup_response); break; @@ -359,8 +339,8 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e) } break; case SGWC_EVT_SXA_NO_HEARTBEAT: - ogs_warn("No Heartbeat from SGW-U [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("No Heartbeat from SGW-U %s", + ogs_sockaddr_to_string_static(node->addr_list)); OGS_FSM_TRAN(s, sgwc_pfcp_state_will_associate); break; default: diff --git a/src/sgwc/sgwc-sm.c b/src/sgwc/sgwc-sm.c index 1d24945eb..96c7d1272 100644 --- a/src/sgwc/sgwc-sm.c +++ b/src/sgwc/sgwc-sm.c @@ -89,23 +89,12 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) ogs_assert(e); recvbuf = e->pkbuf; ogs_assert(recvbuf); + pfcp_message = e->pfcp_message; + ogs_assert(pfcp_message); pfcp_node = e->pfcp_node; ogs_assert(pfcp_node); ogs_assert(OGS_FSM_STATE(&pfcp_node->sm)); - /* - * Issue #1911 - * - * Because ogs_pfcp_message_t is over 80kb in size, - * it can cause stack overflow. - * To avoid this, the pfcp_message structure uses heap memory. - */ - if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { - ogs_error("ogs_pfcp_parse_msg() failed"); - ogs_pkbuf_free(recvbuf); - break; - } - rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); @@ -113,7 +102,6 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) break; } - e->pfcp_message = pfcp_message; e->pfcp_xact_id = pfcp_xact ? pfcp_xact->id : OGS_INVALID_POOL_ID; e->gtp_message = NULL; diff --git a/src/sgwu/pfcp-path.c b/src/sgwu/pfcp-path.c index 73def6adb..90093543a 100644 --- a/src/sgwu/pfcp-path.c +++ b/src/sgwu/pfcp-path.c @@ -61,8 +61,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; ogs_pfcp_node_t *node = NULL; + ogs_pfcp_message_t *message = NULL; ogs_pfcp_header_t *h = NULL; + ogs_pfcp_status_e pfcp_status;; + ogs_pfcp_node_id_t node_id; + ogs_assert(fd != INVALID_SOCKET); pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); @@ -102,28 +106,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) e = sgwu_event_new(SGWU_EVT_SXA_MESSAGE); ogs_assert(e); - node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - ogs_error("No memory: ogs_pfcp_node_add() failed"); - ogs_pkbuf_free(e->pkbuf); - sgwu_event_free(e); - return; - } - - node->sock = data; - pfcp_node_fsm_init(node, false); + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) { + ogs_error("ogs_pfcp_parse_msg() failed"); + ogs_pkbuf_free(pkbuf); + sgwu_event_free(e); + return; } + + pfcp_status = ogs_pfcp_extract_node_id(message, &node_id); + switch (pfcp_status) { + case OGS_PFCP_STATUS_SUCCESS: + case OGS_PFCP_STATUS_NODE_ID_NONE: + case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT: + ogs_debug("ogs_pfcp_extract_node_id() " + "type [%d] pfcp_status [%d] node_id [%s] from %s", + message->h.type, pfcp_status, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + break; + + case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE: + case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT: + case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND: + case OGS_PFCP_ERROR_UNKNOWN_MESSAGE: + ogs_error("ogs_pfcp_extract_node_id() failed " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + + default: + ogs_error("Unexpected pfcp_status " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + + node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from); + if (!node) { + if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE || + message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) { + ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS); + node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, + &node_id, &from); + if (!node) { + ogs_error("No memory: ogs_pfcp_node_add() failed"); + goto cleanup; + } + ogs_debug("Added PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + + pfcp_node_fsm_init(node, false); + + } else { + ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s", + message->h.type, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + } else { + ogs_debug("Found PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + ogs_expect(OGS_OK == ogs_pfcp_node_merge( + node, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, + &from)); + ogs_debug("Merged PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + } + e->pfcp_node = node; e->pkbuf = pkbuf; + e->pfcp_message = message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); - ogs_pkbuf_free(e->pkbuf); - sgwu_event_free(e); + goto cleanup; } + + return; + +cleanup: + ogs_pkbuf_free(pkbuf); + ogs_pfcp_message_free(message); + sgwu_event_free(e); } int sgwu_pfcp_open(void) diff --git a/src/sgwu/pfcp-sm.c b/src/sgwu/pfcp-sm.c index 9696cf4a7..130a79912 100644 --- a/src/sgwu/pfcp-sm.c +++ b/src/sgwu/pfcp-sm.c @@ -25,7 +25,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data); void sgwu_pfcp_state_initial(ogs_fsm_t *s, sgwu_event_t *e) { - int rv; ogs_pfcp_node_t *node = NULL; ogs_assert(s); @@ -36,10 +35,6 @@ void sgwu_pfcp_state_initial(ogs_fsm_t *s, sgwu_event_t *e) node = e->pfcp_node; ogs_assert(node); - rv = ogs_pfcp_connect( - ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node); - ogs_assert(rv == OGS_OK); - node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, sgwu_timer_no_heartbeat, node); ogs_assert(node->t_no_heartbeat); @@ -63,12 +58,9 @@ void sgwu_pfcp_state_final(ogs_fsm_t *s, sgwu_event_t *e) void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; ogs_assert(s); ogs_assert(e); @@ -96,11 +88,8 @@ void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e) case SGWU_EVT_SXA_TIMER: switch(e->timer_id) { case SGWU_TIMER_ASSOCIATION: - addr = node->sa_list; - ogs_assert(addr); - - ogs_warn("Retry association with peer [%s]:%d failed", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("Retry association with peer failed %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_assert(node->t_association); ogs_timer_start(node->t_association, @@ -155,13 +144,10 @@ void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e) void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; sgwu_sess_t *sess = NULL; ogs_assert(s); @@ -171,14 +157,11 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->id) { case OGS_FSM_ENTRY_SIG: - ogs_info("PFCP associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_start(node->t_no_heartbeat, ogs_local_conf()->time.message.pfcp.no_heartbeat_duration); ogs_assert(OGS_OK == @@ -191,9 +174,8 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e) } break; case OGS_FSM_EXIT_SIG: - ogs_info("PFCP de-associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP de-associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_stop(node->t_no_heartbeat); break; case SGWU_EVT_SXA_MESSAGE: @@ -263,16 +245,14 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e) } break; case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: - ogs_warn("PFCP[REQ] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[REQ] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_up_handle_association_setup_request(node, xact, &message->pfcp_association_setup_request); break; case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: - ogs_warn("PFCP[RSP] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[RSP] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_up_handle_association_setup_response(node, xact, &message->pfcp_association_setup_response); break; @@ -318,8 +298,8 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e) } break; case SGWU_EVT_SXA_NO_HEARTBEAT: - ogs_warn("No Heartbeat from SGW-C [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("No Heartbeat from SGW-C %s", + ogs_sockaddr_to_string_static(node->addr_list)); OGS_FSM_TRAN(s, sgwu_pfcp_state_will_associate); break; default: diff --git a/src/sgwu/sgwu-sm.c b/src/sgwu/sgwu-sm.c index 149070771..960430658 100644 --- a/src/sgwu/sgwu-sm.c +++ b/src/sgwu/sgwu-sm.c @@ -58,21 +58,11 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e) ogs_assert(e); recvbuf = e->pkbuf; ogs_assert(recvbuf); + pfcp_message = e->pfcp_message; + ogs_assert(pfcp_message); node = e->pfcp_node; ogs_assert(node); - - /* - * Issue #1911 - * - * Because ogs_pfcp_message_t is over 80kb in size, - * it can cause stack overflow. - * To avoid this, the pfcp_message structure uses heap memory. - */ - if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { - ogs_error("ogs_pfcp_parse_msg() failed"); - ogs_pkbuf_free(recvbuf); - break; - } + ogs_assert(OGS_FSM_STATE(&node->sm)); rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact); if (rv != OGS_OK) { @@ -81,7 +71,6 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e) break; } - e->pfcp_message = pfcp_message; e->pfcp_xact_id = xact ? xact->id : OGS_INVALID_POOL_ID; ogs_fsm_dispatch(&node->sm, e); if (OGS_FSM_CHECK(&node->sm, sgwu_pfcp_state_exception)) { diff --git a/src/sgwu/sxa-handler.c b/src/sgwu/sxa-handler.c index 887dc73be..5153549ee 100644 --- a/src/sgwu/sxa-handler.c +++ b/src/sgwu/sxa-handler.c @@ -95,7 +95,17 @@ void sgwu_sxa_handle_session_establishment_request( pdr = created_pdr[i]; ogs_assert(pdr); - if (pdr->f_teid_len) + /* + * Only perform TEID restoration via swap when F-TEID.ch is false. + * + * When F-TEID.ch is false, it means the TEID has already been assigned, and + * the restoration process can safely perform the swap. + * + * If F-TEID.ch is true, it indicates that the UPF needs to assign + * a new TEID for the first time, so performing a swap is not appropriate + * in this case. + */ + if (pdr->f_teid.ch == false && pdr->f_teid_len) ogs_pfcp_pdr_swap_teid(pdr); } restoration_indication = true; diff --git a/src/smf/binding.c b/src/smf/binding.c index 139c12b5c..b76fcd742 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -206,15 +206,17 @@ void smf_bearer_binding(smf_sess_t *sess) else bearer->pgw_s5u_teid = ul_pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == + AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo(&bearer->pgw_s5u_addr, - &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == + sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo(&bearer->pgw_s5u_addr6, - &sess->pfcp_node->addr)); + sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); @@ -599,19 +601,37 @@ void smf_qos_flow_binding(smf_sess_t *sess) } else { ogs_assert(strcmp(qos_flow->pcc_rule.id, pcc_rule->id) == 0); - if ((pcc_rule->qos.mbr.downlink && - qos_flow->qos.mbr.downlink != pcc_rule->qos.mbr.downlink) || - (pcc_rule->qos.mbr.uplink && - qos_flow->qos.mbr.uplink != pcc_rule->qos.mbr.uplink) || - (pcc_rule->qos.gbr.downlink && - qos_flow->qos.gbr.downlink != pcc_rule->qos.gbr.downlink) || - (pcc_rule->qos.gbr.uplink && - qos_flow->qos.gbr.uplink != pcc_rule->qos.gbr.uplink)) { - /* Update QoS parameter */ - memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); + /* + * Check if any MBR/GBR value is non-zero. This indicates that + * the flow might require GBR/MBR-specific handling. + */ + if (pcc_rule->qos.mbr.downlink || pcc_rule->qos.mbr.uplink || + pcc_rule->qos.gbr.downlink || pcc_rule->qos.gbr.uplink) { - /* Update Bearer Request encodes updated QoS parameter */ - qos_presence = true; + /* + * If new packet filters are being added, or if any MBR/GBR + * field differs from what is currently set, then we must + * update the QoS parameters. + */ + if ((ogs_list_count(&qos_flow->pf_to_add_list) > 0) || + (qos_flow->qos.mbr.downlink != pcc_rule->qos.mbr.downlink) || + (qos_flow->qos.mbr.uplink != pcc_rule->qos.mbr.uplink) || + (qos_flow->qos.gbr.downlink != pcc_rule->qos.gbr.downlink) || + (qos_flow->qos.gbr.uplink != pcc_rule->qos.gbr.uplink)) { + + /* + * Update the QoS parameters so that the GBR QoS Flow + * Information IE is properly encoded in the upcoming + * signaling (NGAP/PFCP) messages. + */ + memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); + + /* + * Setting 'qos_presence' to true triggers encoding of + * the QoS IE in the subsequent Bearer Request message. + */ + qos_presence = true; + } } } diff --git a/src/smf/context.c b/src/smf/context.c index 56212244a..93c8074ff 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -53,9 +53,11 @@ int smf_use_gy_iface(void) { switch (smf_self()->ctf_config.enabled) { case SMF_CTF_ENABLED_AUTO: - return ogs_diam_app_connected(OGS_DIAM_GY_APPLICATION_ID) ? 1 : 0; + return ogs_diam_is_relay_or_app_advertised( + OGS_DIAM_GY_APPLICATION_ID) ? 1 : 0; case SMF_CTF_ENABLED_YES: - return ogs_diam_app_connected(OGS_DIAM_GY_APPLICATION_ID) ? 1 : -1; + return ogs_diam_is_relay_or_app_advertised( + OGS_DIAM_GY_APPLICATION_ID) ? 1 : -1; case SMF_CTF_ENABLED_NO: return 0; default: @@ -1182,8 +1184,6 @@ static ogs_pfcp_node_t *selected_upf_node( void smf_sess_select_upf(smf_sess_t *sess) { - char buf[OGS_ADDRSTRLEN]; - ogs_assert(sess); /* @@ -1199,8 +1199,9 @@ void smf_sess_select_upf(smf_sess_t *sess) selected_upf_node(ogs_pfcp_self()->pfcp_node, sess); ogs_assert(ogs_pfcp_self()->pfcp_node); OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->pfcp_node); - ogs_debug("UE using UPF on IP[%s]", - OGS_ADDR(&ogs_pfcp_self()->pfcp_node->addr, buf)); + ogs_debug("UE using UPF on IP %s", + ogs_sockaddr_to_string_static( + ogs_pfcp_self()->pfcp_node->addr_list)); } smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type) @@ -1482,6 +1483,7 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi) ogs_list_add(&smf_ue->sess_list, sess); + smf_metrics_inst_global_inc(SMF_METR_GLOB_GAUGE_PFCP_SESSIONS_ACTIVE); stats_add_smf_session(); return sess; @@ -1889,6 +1891,7 @@ void smf_sess_remove(smf_sess_t *sess) smf_metrics_inst_global_dec(SMF_METR_GLOB_GAUGE_GTP2_SESSIONS_ACTIVE); break; } + smf_metrics_inst_global_dec(SMF_METR_GLOB_GAUGE_PFCP_SESSIONS_ACTIVE); stats_remove_smf_session(sess); ogs_pool_free(&smf_n4_seid_pool, sess->smf_n4_seid_node); @@ -2369,14 +2372,16 @@ void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess) else sess->handover.local_dl_teid = pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( &sess->handover.local_dl_addr, - &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == + AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( &sess->handover.local_dl_addr6, - &sess->pfcp_node->addr)); + sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); @@ -2453,6 +2458,7 @@ void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess) ogs_pfcp_far_t *up2cp_far = NULL; ogs_assert(sess); + ogs_assert(sess->session.name); smf_sess_delete_cp_up_data_forwarding(sess); @@ -2460,15 +2466,10 @@ void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess) ogs_assert(cp2up_pdr); sess->cp2up_pdr = cp2up_pdr; -#if 0 - /* - * DEPRECATED: - * In PDR, no need to distinguish the Network Instance from CP to UP. - */ - ogs_assert(sess->session.name); - cp2up_pdr->apn = ogs_strdup(sess->session.name); - ogs_assert(cp2up_pdr->apn); -#endif + if (ogs_global_conf()->parameter.use_upg_vpp == true) { + cp2up_pdr->apn = ogs_strdup(sess->session.name); + ogs_assert(cp2up_pdr->apn); + } cp2up_pdr->src_if = OGS_PFCP_INTERFACE_CP_FUNCTION; @@ -2491,7 +2492,6 @@ void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess) ogs_assert(up2cp_pdr); sess->up2cp_pdr = up2cp_pdr; - ogs_assert(sess->session.name); up2cp_pdr->apn = ogs_strdup(sess->session.name); ogs_assert(up2cp_pdr->apn); @@ -2532,15 +2532,10 @@ void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess) ogs_assert(up2cp_far); sess->up2cp_far = up2cp_far; - ogs_assert(sess->session.name); -#if 0 - /* - * DEPRECATED: - * In FAR, no need to distinguish the Network Instance from CP to UP. - */ - up2cp_far->apn = ogs_strdup(sess->session.name); - ogs_assert(up2cp_far->apn); -#endif + if (ogs_global_conf()->parameter.use_upg_vpp == true) { + up2cp_far->apn = ogs_strdup(sess->session.name); + ogs_assert(up2cp_far->apn); + } up2cp_far->dst_if = OGS_PFCP_INTERFACE_CP_FUNCTION; ogs_pfcp_pdr_associate_far(up2cp_pdr, up2cp_far); @@ -3314,7 +3309,10 @@ int smf_pco_build(uint8_t *pco_buf, uint8_t *buffer, int length) /* TODO */ break; case OGS_PCO_ID_MS_SUPPORT_LOCAL_ADDR_TFT_INDICATOR: - /* TODO */ + smf.ids[smf.num_of_id].id = ue.ids[i].id; + smf.ids[smf.num_of_id].len = 0; + smf.ids[smf.num_of_id].data = 0; + smf.num_of_id++; break; case OGS_PCO_ID_P_CSCF_RE_SELECTION_SUPPORT: /* TODO */ diff --git a/src/smf/context.h b/src/smf/context.h index 48c57ca5a..2790d8c51 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -448,6 +448,7 @@ typedef struct smf_sess_s { /* S_NSSAI */ ogs_s_nssai_t s_nssai; ogs_s_nssai_t mapped_hplmn; + bool mapped_hplmn_presence; /* PDN Configuration */ ogs_session_t session; diff --git a/src/smf/gn-handler.c b/src/smf/gn-handler.c index 73001b347..c4c35b6ca 100644 --- a/src/smf/gn-handler.c +++ b/src/smf/gn-handler.c @@ -110,7 +110,7 @@ uint8_t smf_gn_handle_create_pdp_context_request( cause_value = OGS_GTP1_CAUSE_MANDATORY_IE_MISSING; } - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_GX_APPLICATION_ID)) { ogs_error("No Gx Diameter Peer"); cause_value = OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; } @@ -309,7 +309,7 @@ uint8_t smf_gn_handle_delete_pdp_context_request( { ogs_debug("Delete PDP Context Request"); - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_GX_APPLICATION_ID)) { ogs_error("No Gx Diameter Peer"); return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; } diff --git a/src/smf/gsm-build.c b/src/smf/gsm-build.c index 6024e2eab..a4531d942 100644 --- a/src/smf/gsm-build.c +++ b/src/smf/gsm-build.c @@ -170,7 +170,8 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess) /* S-NSSAI */ pdu_session_establishment_accept->presencemask |= OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_S_NSSAI_PRESENT; - ogs_nas_build_s_nssai2(nas_s_nssai, &sess->s_nssai, &sess->mapped_hplmn); + ogs_nas_build_s_nssai2(nas_s_nssai, &sess->s_nssai, + (sess->mapped_hplmn_presence) ? &sess->mapped_hplmn : NULL); /* QoS flow descriptions */ if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) { diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index e9b6d043e..aba48bd99 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -210,14 +210,15 @@ uint32_t smf_gx_handle_cca_initial_request( else bearer->pgw_s5u_teid = ul_pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &bearer->pgw_s5u_addr, &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + &bearer->pgw_s5u_addr, sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &bearer->pgw_s5u_addr6, &sess->pfcp_node->addr)); + &bearer->pgw_s5u_addr6, sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); diff --git a/src/smf/metrics.c b/src/smf/metrics.c index dd8cf3370..626fd9099 100644 --- a/src/smf/metrics.c +++ b/src/smf/metrics.c @@ -126,6 +126,16 @@ smf_metrics_spec_def_t smf_metrics_spec_def_global[_SMF_METR_GLOB_MAX] = { .name = "gtp_peers_active", .description = "Active GTP peers", }, +[SMF_METR_GLOB_GAUGE_PFCP_SESSIONS_ACTIVE] = { + .type = OGS_METRICS_METRIC_TYPE_GAUGE, + .name = "pfcp_sessions_active", + .description = "Active PFCP Sessions", +}, +[SMF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE] = { + .type = OGS_METRICS_METRIC_TYPE_GAUGE, + .name = "pfcp_peers_active", + .description = "Active PFCP peers", +}, }; int smf_metrics_init_inst_global(void) { diff --git a/src/smf/metrics.h b/src/smf/metrics.h index 8a2209e0c..3cb4991df 100644 --- a/src/smf/metrics.h +++ b/src/smf/metrics.h @@ -24,6 +24,8 @@ typedef enum smf_metric_type_global_s { SMF_METR_GLOB_GAUGE_GTP1_PDPCTXS_ACTIVE, SMF_METR_GLOB_GAUGE_GTP2_SESSIONS_ACTIVE, SMF_METR_GLOB_GAUGE_GTP_PEERS_ACTIVE, + SMF_METR_GLOB_GAUGE_PFCP_SESSIONS_ACTIVE, + SMF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE, _SMF_METR_GLOB_MAX, } smf_metric_type_global_t; extern ogs_metrics_inst_t *smf_metrics_inst_global[_SMF_METR_GLOB_MAX]; diff --git a/src/smf/npcf-handler.c b/src/smf/npcf-handler.c index ef72c6523..d393a1d18 100644 --- a/src/smf/npcf-handler.c +++ b/src/smf/npcf-handler.c @@ -345,7 +345,7 @@ bool smf_npcf_smpolicycontrol_handle_create( ogs_error("[%s:%d] Invalid URI [%s]", smf_ue->supi, sess->psi, header.uri); ogs_sbi_header_free(&header); - return OGS_ERROR; + return false; } client = ogs_sbi_client_find(scheme, fqdn, fqdn_port, addr, addr6); @@ -361,7 +361,7 @@ bool smf_npcf_smpolicycontrol_handle_create( ogs_freeaddrinfo(addr); ogs_freeaddrinfo(addr6); - return OGS_ERROR; + return false; } } @@ -524,16 +524,11 @@ bool smf_npcf_smpolicycontrol_handle_create( &dl_pdr->ue_ip_addr, &dl_pdr->ue_ip_addr_len)); dl_pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST; -#if 0 - /* DEPRECATED: - * - * The UE IP Address is unnecessary in the PDI of the UL PDR - * because the PDR can be found using the TEID. - */ - ogs_assert(OGS_OK == - ogs_pfcp_paa_to_ue_ip_addr(&sess->paa, - &ul_pdr->ue_ip_addr, &ul_pdr->ue_ip_addr_len)); -#endif + if (ogs_global_conf()->parameter.use_upg_vpp == true) { + ogs_assert(OGS_OK == + ogs_pfcp_paa_to_ue_ip_addr(&sess->paa, + &ul_pdr->ue_ip_addr, &ul_pdr->ue_ip_addr_len)); + } if (sess->session.ipv4_framed_routes && sess->pfcp_node->up_function_features.frrt) { @@ -664,14 +659,15 @@ bool smf_npcf_smpolicycontrol_handle_create( else sess->local_ul_teid = ul_pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_ul_addr, &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + &sess->local_ul_addr, sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_ul_addr6, &sess->pfcp_node->addr)); + &sess->local_ul_addr6, sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index ac555c74e..777bd7935 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -290,6 +290,7 @@ bool smf_nsmf_handle_create_sm_context( sess->s_nssai.sst = sNssai->sst; sess->s_nssai.sd = ogs_s_nssai_sd_from_string(sNssai->sd); if (SmContextCreateData->hplmn_snssai) { + sess->mapped_hplmn_presence = true; sess->mapped_hplmn.sst = SmContextCreateData->hplmn_snssai->sst; sess->mapped_hplmn.sd = ogs_s_nssai_sd_from_string( SmContextCreateData->hplmn_snssai->sd); @@ -532,14 +533,15 @@ bool smf_nsmf_handle_create_sm_context( else sess->local_dl_teid = dl_pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_dl_addr, &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + &sess->local_dl_addr, sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_dl_addr6, &sess->pfcp_node->addr)); + &sess->local_dl_addr6, sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); @@ -565,14 +567,15 @@ bool smf_nsmf_handle_create_sm_context( else sess->local_ul_teid = ul_pdr->teid; } else { - if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) + ogs_assert(sess->pfcp_node->addr_list); + if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_ul_addr, &sess->pfcp_node->addr)); - else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) + &sess->local_ul_addr, sess->pfcp_node->addr_list)); + else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6) ogs_assert(OGS_OK == ogs_copyaddrinfo( - &sess->local_ul_addr6, &sess->pfcp_node->addr)); + &sess->local_ul_addr6, sess->pfcp_node->addr_list)); else ogs_assert_if_reached(); @@ -2126,5 +2129,5 @@ cleanup: ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - return OGS_OK; + return true; } diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 8ed2f143b..460b09fb6 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -101,8 +101,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; ogs_pfcp_node_t *node = NULL; + ogs_pfcp_message_t *message = NULL; ogs_pfcp_header_t *h = NULL; + ogs_pfcp_status_e pfcp_status;; + ogs_pfcp_node_id_t node_id; + ogs_assert(fd != INVALID_SOCKET); pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); @@ -142,28 +146,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) e = smf_event_new(SMF_EVT_N4_MESSAGE); ogs_assert(e); - node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - ogs_error("No memory: ogs_pfcp_node_add() failed"); - ogs_pkbuf_free(e->pkbuf); - ogs_event_free(e); - return; - } - - node->sock = data; - pfcp_node_fsm_init(node, false); + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) { + ogs_error("ogs_pfcp_parse_msg() failed"); + ogs_pkbuf_free(pkbuf); + ogs_event_free(e); + return; } + + pfcp_status = ogs_pfcp_extract_node_id(message, &node_id); + switch (pfcp_status) { + case OGS_PFCP_STATUS_SUCCESS: + case OGS_PFCP_STATUS_NODE_ID_NONE: + case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT: + ogs_debug("ogs_pfcp_extract_node_id() " + "type [%d] pfcp_status [%d] node_id [%s] from %s", + message->h.type, pfcp_status, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + break; + + case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE: + case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT: + case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND: + case OGS_PFCP_ERROR_UNKNOWN_MESSAGE: + ogs_error("ogs_pfcp_extract_node_id() failed " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + + default: + ogs_error("Unexpected pfcp_status " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + + node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from); + if (!node) { + if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE || + message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) { + ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS); + node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, + &node_id, &from); + if (!node) { + ogs_error("No memory: ogs_pfcp_node_add() failed"); + goto cleanup; + } + ogs_debug("Added PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + + pfcp_node_fsm_init(node, false); + + } else { + ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s", + message->h.type, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + } else { + ogs_debug("Found PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + ogs_expect(OGS_OK == ogs_pfcp_node_merge( + node, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, + &from)); + ogs_debug("Merged PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + } + e->pfcp_node = node; e->pkbuf = pkbuf; + e->pfcp_message = message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); - ogs_pkbuf_free(e->pkbuf); - ogs_event_free(e); + goto cleanup; } + + return; + +cleanup: + ogs_pkbuf_free(pkbuf); + ogs_pfcp_message_free(message); + ogs_event_free(e); } int smf_pfcp_open(void) diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 6cb176441..d7d313441 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -28,7 +28,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data); void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e) { - int rv; ogs_pfcp_node_t *node = NULL; ogs_assert(s); @@ -39,10 +38,6 @@ void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e) node = e->pfcp_node; ogs_assert(node); - rv = ogs_pfcp_connect( - ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node); - ogs_assert(rv == OGS_OK); - node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, smf_timer_pfcp_no_heartbeat, node); ogs_assert(node->t_no_heartbeat); @@ -66,13 +61,10 @@ void smf_pfcp_state_final(ogs_fsm_t *s, smf_event_t *e) void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; smf_sess_t *sess; ogs_assert(s); @@ -82,8 +74,6 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: @@ -107,8 +97,8 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e) node = e->pfcp_node; ogs_assert(node); - ogs_warn("Retry association with peer [%s]:%d failed", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("Retry association with peer failed %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_assert(node->t_association); ogs_timer_start(node->t_association, @@ -179,13 +169,10 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e) void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; smf_sess_t *sess = NULL; ogs_assert(s); @@ -195,14 +182,11 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->h.id) { case OGS_FSM_ENTRY_SIG: - ogs_info("PFCP associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_start(node->t_no_heartbeat, ogs_local_conf()->time.message.pfcp.no_heartbeat_duration); ogs_assert(OGS_OK == @@ -213,12 +197,15 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) node->restoration_required = false; ogs_error("PFCP restoration"); } + + smf_metrics_inst_global_inc(SMF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE); break; case OGS_FSM_EXIT_SIG: - ogs_info("PFCP de-associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP de-associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_stop(node->t_no_heartbeat); + + smf_metrics_inst_global_dec(SMF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE); break; case SMF_EVT_N4_MESSAGE: message = e->pfcp_message; @@ -296,16 +283,14 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) } break; case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: - ogs_warn("PFCP[REQ] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[REQ] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_cp_handle_association_setup_request(node, xact, &message->pfcp_association_setup_request); break; case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: - ogs_warn("PFCP[RSP] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[RSP] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_cp_handle_association_setup_response(node, xact, &message->pfcp_association_setup_response); break; @@ -421,8 +406,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) } break; case SMF_EVT_N4_NO_HEARTBEAT: - ogs_warn("No Heartbeat from UPF [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("No Heartbeat from UPF %s", + ogs_sockaddr_to_string_static(node->addr_list)); /* * reselect_upf() should not be executed on node_timeout diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index d37683c73..d03dfa9c7 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -155,7 +155,7 @@ uint8_t smf_s5c_handle_create_session_request( cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_GX_APPLICATION_ID)) { ogs_error("No Gx Diameter Peer"); cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; } @@ -172,7 +172,7 @@ uint8_t smf_s5c_handle_create_session_request( } break; case OGS_GTP2_RAT_TYPE_WLAN: - if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_S6B_APPLICATION_ID)) { ogs_error("No S6b Diameter Peer"); cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; } @@ -485,13 +485,13 @@ uint8_t smf_s5c_handle_delete_session_request( ogs_assert(xact); ogs_assert(req); - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_GX_APPLICATION_ID)) { ogs_error("No Gx Diameter Peer"); return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; } if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { - if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) { + if (!ogs_diam_is_relay_or_app_advertised(OGS_DIAM_S6B_APPLICATION_ID)) { ogs_error("No S6b Diameter Peer"); return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; } diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index b8f4327ed..33c07767d 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -408,23 +408,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(e); recvbuf = e->pkbuf; ogs_assert(recvbuf); + pfcp_message = e->pfcp_message; + ogs_assert(pfcp_message); pfcp_node = e->pfcp_node; ogs_assert(pfcp_node); ogs_assert(OGS_FSM_STATE(&pfcp_node->sm)); - /* - * Issue #1911 - * - * Because ogs_pfcp_message_t is over 80kb in size, - * it can cause stack overflow. - * To avoid this, the pfcp_message structure uses heap memory. - */ - if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { - ogs_error("ogs_pfcp_parse_msg() failed"); - ogs_pkbuf_free(recvbuf); - break; - } - rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); @@ -432,7 +421,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) break; } - e->pfcp_message = pfcp_message; e->pfcp_xact_id = pfcp_xact ? pfcp_xact->id : OGS_INVALID_POOL_ID; e->gtp2_message = NULL; diff --git a/src/udm/nudm-handler.c b/src/udm/nudm-handler.c index 8ce08e7fa..52101b4f0 100644 --- a/src/udm/nudm-handler.c +++ b/src/udm/nudm-handler.c @@ -558,7 +558,7 @@ bool udm_nudm_uecm_handle_smf_registration( return false; } - if (!SmfRegistration->single_nssai || !SmfRegistration->single_nssai->sst) { + if (!SmfRegistration->single_nssai) { ogs_error("[%s:%d] No singleNssai", udm_ue->supi, sess->psi); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, diff --git a/src/udm/nudr-handler.c b/src/udm/nudr-handler.c index a6050bda6..027482048 100644 --- a/src/udm/nudr-handler.c +++ b/src/udm/nudr-handler.c @@ -808,8 +808,7 @@ bool udm_nudr_dr_handle_smf_registration( return false; } - if (!SmfRegistration->single_nssai || - !SmfRegistration->single_nssai->sst) { + if (!SmfRegistration->single_nssai) { ogs_error("[%s:%d] No singleNssai", udm_ue->supi, sess->psi); ogs_assert(true == ogs_sbi_server_send_error( diff --git a/src/upf/context.c b/src/upf/context.c index 7c286fa82..84b1d3057 100644 --- a/src/upf/context.c +++ b/src/upf/context.c @@ -682,9 +682,12 @@ uint8_t upf_sess_set_ue_ipv6_framed_routes(upf_sess_t *sess, void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bool is_uplink) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; uint64_t vol; + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; + /* Increment total & ul octets + pkts */ urr_acc->total_octets += size; urr_acc->total_pkts++; @@ -722,10 +725,13 @@ void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bo void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *urr, ogs_pfcp_user_plane_report_t *report, unsigned int idx) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; ogs_time_t last_report_timestamp; ogs_time_t now; + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; + now = ogs_time_now(); /* we need UTC for start_time and end_time */ if (urr_acc->last_report.timestamp) @@ -780,7 +786,11 @@ void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t * void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; + + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; + urr_acc->last_report.total_octets = urr_acc->total_octets; urr_acc->last_report.dl_octets = urr_acc->dl_octets; urr_acc->last_report.ul_octets = urr_acc->ul_octets; @@ -816,7 +826,10 @@ static void upf_sess_urr_acc_timers_cb(void *data) static void upf_sess_urr_acc_validity_time_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; + + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; ogs_debug("Installing URR Quota Validity Time timer"); urr_acc->reporting_enabled = true; @@ -829,7 +842,10 @@ static void upf_sess_urr_acc_validity_time_setup(upf_sess_t *sess, ogs_pfcp_urr_ static void upf_sess_urr_acc_time_quota_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; + + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; ogs_debug("Installing URR Time Quota timer"); urr_acc->reporting_enabled = true; @@ -841,7 +857,10 @@ static void upf_sess_urr_acc_time_quota_setup(upf_sess_t *sess, ogs_pfcp_urr_t * static void upf_sess_urr_acc_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; + + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; ogs_debug("Installing URR Time Threshold timer"); urr_acc->reporting_enabled = true; @@ -854,7 +873,11 @@ static void upf_sess_urr_acc_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr void upf_sess_urr_acc_timers_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr) { - upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id]; + upf_sess_urr_acc_t *urr_acc = NULL; + + ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR); + urr_acc = &sess->urr_acc[urr->id-1]; + urr_acc->time_start = ogs_time_ntp32_now(); if (urr->rep_triggers.quota_validity_time && urr->quota_validity_time > 0) upf_sess_urr_acc_validity_time_setup(sess, urr); diff --git a/src/upf/metrics.c b/src/upf/metrics.c index 5f280404f..1a0ca1f0d 100644 --- a/src/upf/metrics.c +++ b/src/upf/metrics.c @@ -82,6 +82,11 @@ upf_metrics_spec_def_t upf_metrics_spec_def_global[_UPF_METR_GLOB_MAX] = { .name = "fivegs_upffunction_upf_sessionnbr", .description = "Active Sessions", }, +[UPF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE] = { + .type = OGS_METRICS_METRIC_TYPE_GAUGE, + .name = "pfcp_peers_active", + .description = "Active PFCP peers", +}, }; int upf_metrics_init_inst_global(void) { diff --git a/src/upf/metrics.h b/src/upf/metrics.h index d4e930218..5df082bf0 100644 --- a/src/upf/metrics.h +++ b/src/upf/metrics.h @@ -15,6 +15,7 @@ typedef enum upf_metric_type_global_s { UPF_METR_GLOB_CTR_SM_N4SESSIONREPORT, UPF_METR_GLOB_CTR_SM_N4SESSIONREPORTSUCC, UPF_METR_GLOB_GAUGE_UPF_SESSIONNBR, + UPF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE, _UPF_METR_GLOB_MAX, } upf_metric_type_global_t; extern ogs_metrics_inst_t *upf_metrics_inst_global[_UPF_METR_GLOB_MAX]; diff --git a/src/upf/n4-handler.c b/src/upf/n4-handler.c index 9e4690da2..18d7e836b 100644 --- a/src/upf/n4-handler.c +++ b/src/upf/n4-handler.c @@ -152,7 +152,17 @@ void upf_n4_handle_session_establishment_request( pdr = created_pdr[i]; ogs_assert(pdr); - if (pdr->f_teid_len) + /* + * Only perform TEID restoration via swap when F-TEID.ch is false. + * + * When F-TEID.ch is false, it means the TEID has already been assigned, and + * the restoration process can safely perform the swap. + * + * If F-TEID.ch is true, it indicates that the UPF needs to assign + * a new TEID for the first time, so performing a swap is not appropriate + * in this case. + */ + if (pdr->f_teid.ch == false && pdr->f_teid_len) ogs_pfcp_pdr_swap_teid(pdr); } restoration_indication = true; diff --git a/src/upf/pfcp-path.c b/src/upf/pfcp-path.c index ea4591dce..bd5c5d03a 100644 --- a/src/upf/pfcp-path.c +++ b/src/upf/pfcp-path.c @@ -64,8 +64,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) ogs_pkbuf_t *pkbuf = NULL; ogs_sockaddr_t from; ogs_pfcp_node_t *node = NULL; + ogs_pfcp_message_t *message = NULL; ogs_pfcp_header_t *h = NULL; + ogs_pfcp_status_e pfcp_status;; + ogs_pfcp_node_id_t node_id; + ogs_assert(fd != INVALID_SOCKET); pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); @@ -105,28 +109,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) e = upf_event_new(UPF_EVT_N4_MESSAGE); ogs_assert(e); - node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from); - if (!node) { - ogs_error("No memory: ogs_pfcp_node_add() failed"); - ogs_pkbuf_free(e->pkbuf); - upf_event_free(e); - return; - } - - node->sock = data; - pfcp_node_fsm_init(node, false); + /* + * Issue #1911 + * + * Because ogs_pfcp_message_t is over 80kb in size, + * it can cause stack overflow. + * To avoid this, the pfcp_message structure uses heap memory. + */ + if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) { + ogs_error("ogs_pfcp_parse_msg() failed"); + ogs_pkbuf_free(pkbuf); + upf_event_free(e); + return; } + + pfcp_status = ogs_pfcp_extract_node_id(message, &node_id); + switch (pfcp_status) { + case OGS_PFCP_STATUS_SUCCESS: + case OGS_PFCP_STATUS_NODE_ID_NONE: + case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT: + ogs_debug("ogs_pfcp_extract_node_id() " + "type [%d] pfcp_status [%d] node_id [%s] from %s", + message->h.type, pfcp_status, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + break; + + case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE: + case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT: + case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND: + case OGS_PFCP_ERROR_UNKNOWN_MESSAGE: + ogs_error("ogs_pfcp_extract_node_id() failed " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + + default: + ogs_error("Unexpected pfcp_status " + "type [%d] pfcp_status [%d] from %s", + message->h.type, pfcp_status, + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + + node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from); + if (!node) { + if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE || + message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) { + ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS); + node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, + &node_id, &from); + if (!node) { + ogs_error("No memory: ogs_pfcp_node_add() failed"); + goto cleanup; + } + ogs_debug("Added PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + + pfcp_node_fsm_init(node, false); + + } else { + ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s", + message->h.type, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? + ogs_pfcp_node_id_to_string_static(&node_id) : + "NULL", + ogs_sockaddr_to_string_static(&from)); + goto cleanup; + } + } else { + ogs_debug("Found PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + ogs_expect(OGS_OK == ogs_pfcp_node_merge( + node, + pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, + &from)); + ogs_debug("Merged PFCP-Node: addr_list %s", + ogs_sockaddr_to_string_static(node->addr_list)); + } + e->pfcp_node = node; e->pkbuf = pkbuf; + e->pfcp_message = message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { ogs_error("ogs_queue_push() failed:%d", (int)rv); - ogs_pkbuf_free(e->pkbuf); - upf_event_free(e); + goto cleanup; } + + return; + +cleanup: + ogs_pkbuf_free(pkbuf); + ogs_pfcp_message_free(message); + upf_event_free(e); } int upf_pfcp_open(void) diff --git a/src/upf/pfcp-sm.c b/src/upf/pfcp-sm.c index 7a1f74b94..27499ef44 100644 --- a/src/upf/pfcp-sm.c +++ b/src/upf/pfcp-sm.c @@ -30,7 +30,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data); void upf_pfcp_state_initial(ogs_fsm_t *s, upf_event_t *e) { - int rv; ogs_pfcp_node_t *node = NULL; ogs_assert(s); @@ -41,10 +40,6 @@ void upf_pfcp_state_initial(ogs_fsm_t *s, upf_event_t *e) node = e->pfcp_node; ogs_assert(node); - rv = ogs_pfcp_connect( - ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node); - ogs_assert(rv == OGS_OK); - node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, upf_timer_no_heartbeat, node); ogs_assert(node->t_no_heartbeat); @@ -68,12 +63,9 @@ void upf_pfcp_state_final(ogs_fsm_t *s, upf_event_t *e) void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; ogs_assert(s); ogs_assert(e); @@ -101,11 +93,8 @@ void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e) case UPF_EVT_N4_TIMER: switch(e->timer_id) { case UPF_TIMER_ASSOCIATION: - addr = node->sa_list; - ogs_assert(addr); - - ogs_warn("Retry association with peer [%s]:%d failed", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("Retry association with peer failed %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_assert(node->t_association); ogs_timer_start(node->t_association, @@ -160,13 +149,10 @@ void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e) void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e) { - char buf[OGS_ADDRSTRLEN]; - ogs_pfcp_node_t *node = NULL; ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_message_t *message = NULL; - ogs_sockaddr_t *addr = NULL; upf_sess_t *sess = NULL; ogs_assert(s); @@ -176,14 +162,11 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e) node = e->pfcp_node; ogs_assert(node); - addr = node->sa_list; - ogs_assert(addr); switch (e->id) { case OGS_FSM_ENTRY_SIG: - ogs_info("PFCP associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_start(node->t_no_heartbeat, ogs_local_conf()->time.message.pfcp.no_heartbeat_duration); ogs_assert(OGS_OK == @@ -194,12 +177,15 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e) node->restoration_required = false; ogs_error("PFCP restoration"); } + + upf_metrics_inst_global_inc(UPF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE); break; case OGS_FSM_EXIT_SIG: - ogs_info("PFCP de-associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_info("PFCP de-associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_timer_stop(node->t_no_heartbeat); + + upf_metrics_inst_global_dec(UPF_METR_GLOB_GAUGE_PFCP_PEERS_ACTIVE); break; case UPF_EVT_N4_MESSAGE: message = e->pfcp_message; @@ -267,16 +253,14 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e) } break; case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE: - ogs_warn("PFCP[REQ] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[REQ] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_up_handle_association_setup_request(node, xact, &message->pfcp_association_setup_request); break; case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE: - ogs_warn("PFCP[RSP] has already been associated [%s]:%d", - OGS_ADDR(&node->addr, buf), - OGS_PORT(&node->addr)); + ogs_warn("PFCP[RSP] has already been associated %s", + ogs_sockaddr_to_string_static(node->addr_list)); ogs_pfcp_up_handle_association_setup_response(node, xact, &message->pfcp_association_setup_response); break; @@ -322,8 +306,8 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e) } break; case UPF_EVT_N4_NO_HEARTBEAT: - ogs_warn("No Heartbeat from SMF [%s]:%d", - OGS_ADDR(addr, buf), OGS_PORT(addr)); + ogs_warn("No Heartbeat from SMF %s", + ogs_sockaddr_to_string_static(node->addr_list)); OGS_FSM_TRAN(s, upf_pfcp_state_will_associate); break; default: diff --git a/src/upf/upf-sm.c b/src/upf/upf-sm.c index a4e842546..df85d21d7 100644 --- a/src/upf/upf-sm.c +++ b/src/upf/upf-sm.c @@ -63,21 +63,11 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e) ogs_assert(e); recvbuf = e->pkbuf; ogs_assert(recvbuf); + pfcp_message = e->pfcp_message; + ogs_assert(pfcp_message); node = e->pfcp_node; ogs_assert(node); - - /* - * Issue #1911 - * - * Because ogs_pfcp_message_t is over 80kb in size, - * it can cause stack overflow. - * To avoid this, the pfcp_message structure uses heap memory. - */ - if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) { - ogs_error("ogs_pfcp_parse_msg() failed"); - ogs_pkbuf_free(recvbuf); - break; - } + ogs_assert(OGS_FSM_STATE(&node->sm)); rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact); if (rv != OGS_OK) { @@ -86,7 +76,6 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e) break; } - e->pfcp_message = pfcp_message; e->pfcp_xact_id = xact ? xact->id : OGS_INVALID_POOL_ID; ogs_fsm_dispatch(&node->sm, e); if (OGS_FSM_CHECK(&node->sm, upf_pfcp_state_exception)) { diff --git a/tests/af/npcf-build.c b/tests/af/npcf-build.c index 688a72f66..136106aff 100644 --- a/tests/af/npcf-build.c +++ b/tests/af/npcf-build.c @@ -115,11 +115,9 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( AscReqData.ev_subsc = &evSubsc; memset(&sNssai, 0, sizeof(sNssai)); - if (sess->s_nssai.sst) { - sNssai.sst = sess->s_nssai.sst; - sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); - AscReqData.slice_info = &sNssai; - } + sNssai.sst = sess->s_nssai.sst; + sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); + AscReqData.slice_info = &sNssai; AscReqData.spon_status = OpenAPI_sponsoring_status_SPONSOR_DISABLED; @@ -709,11 +707,10 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create_video( AscReqData.ev_subsc = &evSubsc; memset(&sNssai, 0, sizeof(sNssai)); - if (sess->s_nssai.sst) { - sNssai.sst = sess->s_nssai.sst; - sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); - AscReqData.slice_info = &sNssai; - } + + sNssai.sst = sess->s_nssai.sst; + sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); + AscReqData.slice_info = &sNssai; AscReqData.spon_status = OpenAPI_sponsoring_status_SPONSOR_DISABLED; diff --git a/tests/common/context.c b/tests/common/context.c index a584dcd7e..cc879de0c 100644 --- a/tests/common/context.c +++ b/tests/common/context.c @@ -1174,6 +1174,7 @@ test_ue_t *test_ue_add_by_suci( s_nssai->sst = 0; s_nssai->sd.v = OGS_S_NSSAI_NO_SD_VALUE; + s_nssai->mapped_hplmn_sst_presence = false; s_nssai->mapped_hplmn_sst = 0; s_nssai->mapped_hplmn_sd.v = OGS_S_NSSAI_NO_SD_VALUE; diff --git a/tests/common/sctp.c b/tests/common/sctp.c index a08bcca7c..575d8ca08 100644 --- a/tests/common/sctp.c +++ b/tests/common/sctp.c @@ -54,7 +54,7 @@ ogs_socknode_t *testsctp_client(const char *ipstr, int port) node = ogs_socknode_new(addr); ogs_assert(node); - sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL, NULL); ogs_assert(sock); node->sock = sock; @@ -82,7 +82,7 @@ ogs_socknode_t *tests1ap_client(int family) node = ogs_socknode_new(addr); ogs_assert(node); - sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL, NULL); ogs_assert(sock); node->sock = sock; @@ -121,7 +121,7 @@ ogs_socknode_t *testngap_client(int index, int family) node = ogs_socknode_new(addr); ogs_assert(node); - sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL); + sock = ogs_sctp_client(SOCK_STREAM, node->addr, NULL, NULL); ogs_assert(sock); node->sock = sock; diff --git a/tests/handover/5gc-n2-test.c b/tests/handover/5gc-n2-test.c index 8b7f4323c..b8f355e3c 100644 --- a/tests/handover/5gc-n2-test.c +++ b/tests/handover/5gc-n2-test.c @@ -515,7 +515,7 @@ static void direct_complete_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, gtpu2); /* NG-Setup Reqeust/Response for Source gNB */ - sendbuf = testngap_build_ng_setup_request(0x4000, 28); + sendbuf = testngap_build_ng_setup_request(0, 28); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -769,7 +769,7 @@ static void direct_complete_func(abts_case *tc, void *data) /* Send UplinkRANConfigurationTransfer */ sendbuf = testngap_build_uplink_ran_configuration_transfer( - 0x4000, 28, 0x4001, 28); + 0, 28, 0x4001, 28); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -781,7 +781,7 @@ static void direct_complete_func(abts_case *tc, void *data) /* Send UplinkRANConfigurationTransfer */ sendbuf = testngap_build_uplink_ran_configuration_transfer( - 0x4001, 28, 0x4000, 28); + 0x4001, 28, 0, 28); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap2, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -911,7 +911,7 @@ static void direct_complete_func(abts_case *tc, void *data) /* Send HandoverRequired */ sendbuf = testngap_build_handover_required( test_ue, NGAP_HandoverType_intra5gs, - 0x4000, 28, + 0, 28, NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason, true); diff --git a/tests/sctp/sctp-test.c b/tests/sctp/sctp-test.c index 288e06b44..436185293 100644 --- a/tests/sctp/sctp-test.c +++ b/tests/sctp/sctp-test.c @@ -53,7 +53,7 @@ static void test1_func(abts_case *tc, void *data) rv = ogs_freeaddrinfo(addr); ABTS_INT_EQUAL(tc, OGS_OK, rv); - rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST1_PORT2, AI_PASSIVE); + rv = ogs_getaddrinfo(&addr, AF_INET6, NULL, TEST1_PORT2, AI_PASSIVE); ABTS_INT_EQUAL(tc, OGS_OK, rv); sctp = ogs_sctp_server(SOCK_SEQPACKET, addr, NULL); ABTS_PTR_NOTNULL(tc, sctp); @@ -77,7 +77,7 @@ static void test2_main(void *data) rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST2_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - sctp = ogs_sctp_client(SOCK_SEQPACKET, addr, NULL); + sctp = ogs_sctp_client(SOCK_SEQPACKET, addr, NULL, NULL); ABTS_PTR_NOTNULL(tc, sctp); size = ogs_sctp_recvdata(sctp, str, STRLEN, &from, &sinfo); @@ -192,7 +192,7 @@ static void test4_main(void *data) rv = ogs_getaddrinfo(&addr, AF_UNSPEC, NULL, TEST4_PORT, 0); ABTS_INT_EQUAL(tc, OGS_OK, rv); - sctp = ogs_sctp_client(SOCK_STREAM, addr, NULL); + sctp = ogs_sctp_client(SOCK_STREAM, addr, NULL, NULL); ABTS_PTR_NOTNULL(tc, sctp); size = ogs_sctp_sendmsg(sctp, DATASTR, strlen(DATASTR), NULL, PPID, 0); diff --git a/tests/slice/same-dnn-test.c b/tests/slice/same-dnn-test.c index 64263bf6c..f2f90ddb0 100644 --- a/tests/slice/same-dnn-test.c +++ b/tests/slice/same-dnn-test.c @@ -426,6 +426,8 @@ static void test2_func(abts_case *tc, void *data) sst = 2; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. sd.v = OGS_S_NSSAI_NO_SD_VALUE; + test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. + mapped_hplmn_sst_presence = false; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. mapped_hplmn_sst = 0; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. @@ -436,6 +438,8 @@ static void test2_func(abts_case *tc, void *data) sst = 3; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. sd.v = 0x000080; + test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. + mapped_hplmn_sst_presence = false; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai]. mapped_hplmn_sst = 0; test_ue->requested_nssai.s_nssai[test_ue->requested_nssai.num_of_s_nssai].