From a9eaed18aacc7a8ba799e47b04a2b9669b901b5e Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Thu, 21 May 2020 21:24:21 -0400 Subject: [PATCH] NAS-5GS is added --- lib/core/ogs-3gpp-types.h | 1 + lib/nas/5gs/decoder.c | 2817 +++++++++++++ lib/nas/5gs/encoder.c | 3187 ++++++++++++++ lib/nas/5gs/ies.c | 3678 +++++++++++++++++ lib/nas/5gs/ies.h | 273 ++ lib/nas/5gs/meson.build | 37 + lib/nas/5gs/message.h | 1384 +++++++ lib/nas/5gs/ogs-nas-5gs.h | 41 + lib/nas/5gs/support/24501-g41.docx | Bin 0 -> 460032 bytes lib/nas/5gs/support/README.md | 16 + lib/nas/5gs/support/cache/nas-msg-100.py | 3 + lib/nas/5gs/support/cache/nas-msg-101.py | 3 + lib/nas/5gs/support/cache/nas-msg-102.py | 3 + lib/nas/5gs/support/cache/nas-msg-103.py | 12 + lib/nas/5gs/support/cache/nas-msg-104.py | 8 + lib/nas/5gs/support/cache/nas-msg-193.py | 12 + lib/nas/5gs/support/cache/nas-msg-194.py | 4 + lib/nas/5gs/support/cache/nas-msg-195.py | 4 + lib/nas/5gs/support/cache/nas-msg-197.py | 4 + lib/nas/5gs/support/cache/nas-msg-198.py | 14 + lib/nas/5gs/support/cache/nas-msg-199.py | 20 + lib/nas/5gs/support/cache/nas-msg-201.py | 9 + lib/nas/5gs/support/cache/nas-msg-202.py | 4 + lib/nas/5gs/support/cache/nas-msg-203.py | 4 + lib/nas/5gs/support/cache/nas-msg-204.py | 4 + lib/nas/5gs/support/cache/nas-msg-205.py | 13 + lib/nas/5gs/support/cache/nas-msg-209.py | 7 + lib/nas/5gs/support/cache/nas-msg-210.py | 14 + lib/nas/5gs/support/cache/nas-msg-211.py | 4 + lib/nas/5gs/support/cache/nas-msg-212.py | 4 + lib/nas/5gs/support/cache/nas-msg-214.py | 4 + lib/nas/5gs/support/cache/nas-msg-65.py | 35 + lib/nas/5gs/support/cache/nas-msg-66.py | 40 + lib/nas/5gs/support/cache/nas-msg-67.py | 3 + lib/nas/5gs/support/cache/nas-msg-68.py | 7 + lib/nas/5gs/support/cache/nas-msg-69.py | 4 + lib/nas/{ => 5gs}/support/cache/nas-msg-70.py | 0 lib/nas/5gs/support/cache/nas-msg-71.py | 6 + .../support/cache/nas-msg-72.py} | 0 lib/nas/5gs/support/cache/nas-msg-76.py | 8 + lib/nas/5gs/support/cache/nas-msg-77.py | 7 + lib/nas/5gs/support/cache/nas-msg-78.py | 7 + lib/nas/5gs/support/cache/nas-msg-84.py | 25 + lib/nas/5gs/support/cache/nas-msg-85.py | 12 + lib/nas/5gs/support/cache/nas-msg-86.py | 7 + lib/nas/5gs/support/cache/nas-msg-87.py | 4 + lib/nas/5gs/support/cache/nas-msg-88.py | 3 + lib/nas/5gs/support/cache/nas-msg-89.py | 4 + lib/nas/5gs/support/cache/nas-msg-90.py | 5 + lib/nas/5gs/support/cache/nas-msg-91.py | 3 + lib/nas/5gs/support/cache/nas-msg-92.py | 3 + lib/nas/5gs/support/cache/nas-msg-93.py | 11 + lib/nas/5gs/support/cache/nas-msg-94.py | 5 + lib/nas/5gs/support/cache/nas-msg-95.py | 3 + lib/nas/5gs/support/nas-message.py | 965 +++++ lib/nas/5gs/support/type-list.py | 53 + lib/nas/5gs/types.h | 959 +++++ lib/nas/{ => common}/conv.c | 2 +- lib/nas/{ => common}/conv.h | 8 +- lib/nas/common/meson.build | 36 + .../{ogs-nas.h => common/ogs-nas-common.h} | 12 +- lib/nas/{ => common}/types.c | 2 +- lib/nas/common/types.h | 763 ++++ lib/nas/decoder.c | 3030 -------------- lib/nas/eps/decoder.c | 2953 +++++++++++++ lib/nas/{ => eps}/encoder.c | 1126 +++-- lib/nas/{ => eps}/ies.c | 16 +- lib/nas/{ => eps}/ies.h | 8 +- lib/nas/eps/meson.build | 37 + lib/nas/{ => eps}/message.h | 8 +- lib/nas/eps/ogs-nas-eps.h | 41 + lib/nas/{ => eps}/support/24301-d80.docx | Bin lib/nas/{ => eps}/support/README.md | 0 .../{ => eps}/support/cache/nas-msg-100.py | 0 .../{ => eps}/support/cache/nas-msg-101.py | 0 .../{ => eps}/support/cache/nas-msg-104.py | 0 .../{ => eps}/support/cache/nas-msg-193.py | 0 .../{ => eps}/support/cache/nas-msg-194.py | 0 .../{ => eps}/support/cache/nas-msg-195.py | 0 .../{ => eps}/support/cache/nas-msg-197.py | 0 .../{ => eps}/support/cache/nas-msg-198.py | 0 .../{ => eps}/support/cache/nas-msg-199.py | 0 .../{ => eps}/support/cache/nas-msg-201.py | 0 .../{ => eps}/support/cache/nas-msg-202.py | 0 .../{ => eps}/support/cache/nas-msg-203.py | 0 .../{ => eps}/support/cache/nas-msg-205.py | 0 .../{ => eps}/support/cache/nas-msg-206.py | 0 .../{ => eps}/support/cache/nas-msg-208.py | 0 .../{ => eps}/support/cache/nas-msg-209.py | 0 .../{ => eps}/support/cache/nas-msg-210.py | 0 .../{ => eps}/support/cache/nas-msg-211.py | 0 .../{ => eps}/support/cache/nas-msg-212.py | 0 .../{ => eps}/support/cache/nas-msg-213.py | 0 .../{ => eps}/support/cache/nas-msg-214.py | 0 .../{ => eps}/support/cache/nas-msg-215.py | 0 .../support/cache/nas-msg-217.py} | 0 .../{ => eps}/support/cache/nas-msg-218.py | 0 .../{ => eps}/support/cache/nas-msg-232.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-65.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-66.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-67.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-68.py | 0 .../{ => eps}/support/cache/nas-msg-69.1.py | 0 .../{ => eps}/support/cache/nas-msg-69.2.py | 0 .../support/cache/nas-msg-70.py} | 0 lib/nas/{ => eps}/support/cache/nas-msg-72.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-73.py | 0 .../support/cache/nas-msg-74.py} | 0 lib/nas/{ => eps}/support/cache/nas-msg-75.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-76.py | 0 .../{ => eps}/support/cache/nas-msg-77.1.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-78.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-80.py | 0 lib/nas/eps/support/cache/nas-msg-81.py | 2 + lib/nas/{ => eps}/support/cache/nas-msg-82.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-83.py | 0 lib/nas/eps/support/cache/nas-msg-84.py | 2 + lib/nas/{ => eps}/support/cache/nas-msg-85.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-86.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-92.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-93.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-94.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-95.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-96.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-97.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-98.py | 0 lib/nas/{ => eps}/support/cache/nas-msg-99.py | 0 lib/nas/{ => eps}/support/nas-message.py | 143 +- lib/nas/{ => eps}/support/type-list.py | 12 +- lib/nas/{ => eps}/types.h | 720 +--- lib/nas/meson.build | 32 +- src/mme/emm-build.c | 4 +- src/mme/meson.build | 4 +- src/mme/mme-context.h | 2 +- src/mme/s1ap-sm.c | 2 +- 135 files changed, 18180 insertions(+), 4552 deletions(-) create mode 100644 lib/nas/5gs/decoder.c create mode 100644 lib/nas/5gs/encoder.c create mode 100644 lib/nas/5gs/ies.c create mode 100644 lib/nas/5gs/ies.h create mode 100644 lib/nas/5gs/meson.build create mode 100644 lib/nas/5gs/message.h create mode 100644 lib/nas/5gs/ogs-nas-5gs.h create mode 100644 lib/nas/5gs/support/24501-g41.docx create mode 100644 lib/nas/5gs/support/README.md create mode 100644 lib/nas/5gs/support/cache/nas-msg-100.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-101.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-102.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-103.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-104.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-193.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-194.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-195.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-197.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-198.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-199.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-201.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-202.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-203.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-204.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-205.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-209.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-210.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-211.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-212.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-214.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-65.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-66.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-67.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-68.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-69.py rename lib/nas/{ => 5gs}/support/cache/nas-msg-70.py (100%) create mode 100644 lib/nas/5gs/support/cache/nas-msg-71.py rename lib/nas/{support/cache/nas-msg-217.py => 5gs/support/cache/nas-msg-72.py} (100%) create mode 100644 lib/nas/5gs/support/cache/nas-msg-76.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-77.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-78.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-84.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-85.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-86.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-87.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-88.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-89.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-90.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-91.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-92.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-93.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-94.py create mode 100644 lib/nas/5gs/support/cache/nas-msg-95.py create mode 100644 lib/nas/5gs/support/nas-message.py create mode 100644 lib/nas/5gs/support/type-list.py create mode 100644 lib/nas/5gs/types.h rename lib/nas/{ => common}/conv.c (99%) rename lib/nas/{ => common}/conv.h (91%) create mode 100644 lib/nas/common/meson.build rename lib/nas/{ogs-nas.h => common/ogs-nas-common.h} (87%) rename lib/nas/{ => common}/types.c (99%) create mode 100644 lib/nas/common/types.h delete mode 100644 lib/nas/decoder.c create mode 100644 lib/nas/eps/decoder.c rename lib/nas/{ => eps}/encoder.c (86%) rename lib/nas/{ => eps}/ies.c (99%) rename lib/nas/{ => eps}/ies.h (99%) create mode 100644 lib/nas/eps/meson.build rename lib/nas/{ => eps}/message.h (99%) create mode 100644 lib/nas/eps/ogs-nas-eps.h rename lib/nas/{ => eps}/support/24301-d80.docx (100%) rename lib/nas/{ => eps}/support/README.md (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-100.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-101.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-104.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-193.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-194.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-195.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-197.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-198.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-199.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-201.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-202.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-203.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-205.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-206.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-208.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-209.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-210.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-211.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-212.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-213.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-214.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-215.py (100%) rename lib/nas/{support/cache/nas-msg-74.py => eps/support/cache/nas-msg-217.py} (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-218.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-232.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-65.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-66.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-67.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-68.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-69.1.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-69.2.py (100%) rename lib/nas/{support/cache/nas-msg-81.py => eps/support/cache/nas-msg-70.py} (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-72.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-73.py (100%) rename lib/nas/{support/cache/nas-msg-84.py => eps/support/cache/nas-msg-74.py} (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-75.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-76.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-77.1.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-78.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-80.py (100%) create mode 100644 lib/nas/eps/support/cache/nas-msg-81.py rename lib/nas/{ => eps}/support/cache/nas-msg-82.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-83.py (100%) create mode 100644 lib/nas/eps/support/cache/nas-msg-84.py rename lib/nas/{ => eps}/support/cache/nas-msg-85.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-86.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-92.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-93.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-94.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-95.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-96.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-97.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-98.py (100%) rename lib/nas/{ => eps}/support/cache/nas-msg-99.py (100%) rename lib/nas/{ => eps}/support/nas-message.py (91%) rename lib/nas/{ => eps}/support/type-list.py (95%) rename lib/nas/{ => eps}/types.h (55%) diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index f122da77c..9480e0995 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -47,6 +47,7 @@ extern "C" { #define OGS_MAX_NUM_OF_HOSTNAME 16 #define OGS_MAX_APN_LEN 100 +#define OGS_MAX_DNN_LEN 100 #define OGS_MAX_PCO_LEN 251 #define OGS_MAX_FQDN_LEN 256 #define OGS_MAX_IFNAME_LEN 32 diff --git a/lib/nas/5gs/decoder.c b/lib/nas/5gs/decoder.c new file mode 100644 index 000000000..5558e979c --- /dev/null +++ b/lib/nas/5gs/decoder.c @@ -0,0 +1,2817 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 21:20:09.040737 by acetcom + * from 24501-g41.docx + ******************************************************************************/ + +#include "ogs-nas-5gs.h" + +int ogs_nas_decode_registration_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_registration_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_registration_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_registration_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_deregistration_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_deregistration_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_configuration_update_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_configuration_update_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_result(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gmm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_notification_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ul_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_dl_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_establishment_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_establishment_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_establishment_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_authentication_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_authentication_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_authentication_result(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_modification_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_modification_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_modification_command_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_release_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_release_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_release_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_release_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gsm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_registration_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_registration_request_t *registration_request = &message->gmm.registration_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode REGISTRATION_REQUEST\n"); + + size = ogs_nas_decode_5gs_registration_type(®istration_request->registration_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_5gs_mobile_identity(®istration_request->mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE: + size = ogs_nas_decode_key_set_identifier(®istration_request->non_current_native_nas_key_set_identifier, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE: + size = ogs_nas_decode_5gmm_capability(®istration_request->gmm_capability, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE: + size = ogs_nas_decode_ue_security_capability(®istration_request->ue_security_capability, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_TYPE: + size = ogs_nas_decode_nssai(®istration_request->requested_nssai, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE: + size = ogs_nas_decode_5gs_tracking_area_identity(®istration_request->last_visited_registered_tai, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_TYPE: + size = ogs_nas_decode_s1_ue_network_capability(®istration_request->s1_ue_network_capability, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_TYPE: + size = ogs_nas_decode_uplink_data_status(®istration_request->uplink_data_status, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(®istration_request->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_TYPE: + size = ogs_nas_decode_mico_indication(®istration_request->mico_indication, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_TYPE: + size = ogs_nas_decode_ue_status(®istration_request->ue_status, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_TYPE: + size = ogs_nas_decode_5gs_mobile_identity(®istration_request->additional_guti, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_allowed_pdu_session_status(®istration_request->allowed_pdu_session_status, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_TYPE: + size = ogs_nas_decode_ue_usage_setting(®istration_request->ue_usage_setting, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_5gs_drx_parameters(®istration_request->requested_drx_parameters, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_eps_nas_message_container(®istration_request->eps_nas_message_container, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_TYPE: + size = ogs_nas_decode_ladn_indication(®istration_request->ladn_indication, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE: + size = ogs_nas_decode_payload_container_type(®istration_request->payload_container_type, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE: + size = ogs_nas_decode_payload_container(®istration_request->payload_container, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_TYPE: + size = ogs_nas_decode_network_slicing_indication(®istration_request->network_slicing_indication, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_TYPE: + size = ogs_nas_decode_5gs_update_type(®istration_request->update_type, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE: + size = ogs_nas_decode_mobile_station_classmark_2(®istration_request->mobile_station_classmark_2, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_TYPE: + size = ogs_nas_decode_supported_codec_list(®istration_request->supported_codecs, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_message_container(®istration_request->nas_message_container, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE: + size = ogs_nas_decode_eps_bearer_context_status(®istration_request->eps_bearer_context_status, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(®istration_request->requested_extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(®istration_request->t3324_value, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_TYPE: + size = ogs_nas_decode_ue_radio_capability_id(®istration_request->ue_radio_capability_id, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_TYPE: + size = ogs_nas_decode_mapped_nssai(®istration_request->requested_mapped_nssai, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_TYPE: + size = ogs_nas_decode_additional_information_requested(®istration_request->additional_information_requested, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_TYPE: + size = ogs_nas_decode_wus_assistance_information(®istration_request->requested_wus_assistance_information, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_TYPE: + size = ogs_nas_decode_n5gc_indication(®istration_request->n5gc_indication, pkbuf); + ogs_assert(size >= 0); + registration_request->presencemask |= OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_registration_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_registration_accept_t *registration_accept = &message->gmm.registration_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode REGISTRATION_ACCEPT\n"); + + size = ogs_nas_decode_5gs_registration_result(®istration_accept->registration_result, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_TYPE: + size = ogs_nas_decode_5gs_mobile_identity(®istration_accept->guti, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_TYPE: + size = ogs_nas_decode_plmn_list(®istration_accept->equivalent_plmns, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_TYPE: + size = ogs_nas_decode_5gs_tracking_area_identity_list(®istration_accept->tai_list, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_TYPE: + size = ogs_nas_decode_nssai(®istration_accept->allowed_nssai, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_TYPE: + size = ogs_nas_decode_rejected_nssai(®istration_accept->rejected_nssai, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_TYPE: + size = ogs_nas_decode_nssai(®istration_accept->configured_nssai, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_5gs_network_feature_support(®istration_accept->network_feature_support, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(®istration_accept->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE: + size = ogs_nas_decode_pdu_session_reactivation_result(®istration_accept->pdu_session_reactivation_result, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE: + size = ogs_nas_decode_pdu_session_reactivation_result_error_cause(®istration_accept->pdu_session_reactivation_result_error_cause, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_TYPE: + size = ogs_nas_decode_ladn_information(®istration_accept->ladn_information, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_TYPE: + size = ogs_nas_decode_mico_indication(®istration_accept->mico_indication, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_TYPE: + size = ogs_nas_decode_network_slicing_indication(®istration_accept->network_slicing_indication, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_TYPE: + size = ogs_nas_decode_service_area_list(®istration_accept->service_area_list, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(®istration_accept->t3512_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(®istration_accept->non_3gpp_de_registration_timer_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(®istration_accept->t3502_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE: + size = ogs_nas_decode_emergency_number_list(®istration_accept->emergency_number_list, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_TYPE: + size = ogs_nas_decode_extended_emergency_number_list(®istration_accept->extended_emergency_number_list, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_TYPE: + size = ogs_nas_decode_sor_transparent_container(®istration_accept->sor_transparent_container, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(®istration_accept->eap_message, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_TYPE: + size = ogs_nas_decode_nssai_inclusion_mode(®istration_accept->nssai_inclusion_mode, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE: + size = ogs_nas_decode_operator_defined_access_category_definitions(®istration_accept->operator_defined_access_category_definitions, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_5gs_drx_parameters(®istration_accept->negotiated_drx_parameters, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_TYPE: + size = ogs_nas_decode_non_3gpp_nw_provided_policies(®istration_accept->non_3gpp_nw_policies, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE: + size = ogs_nas_decode_eps_bearer_context_status(®istration_accept->eps_bearer_context_status, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(®istration_accept->negotiated_extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(®istration_accept->t3447_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(®istration_accept->t3448_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(®istration_accept->t3324_value, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_TYPE: + size = ogs_nas_decode_ue_radio_capability_id(®istration_accept->ue_radio_capability_id, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE: + size = ogs_nas_decode_ue_radio_capability_id_deletion_indication(®istration_accept->ue_radio_capability_id_deletion_indication, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_TYPE: + size = ogs_nas_decode_nssai(®istration_accept->pending_nssai, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_TYPE: + size = ogs_nas_decode_ciphering_key_data(®istration_accept->ciphering_key_data, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_TYPE: + size = ogs_nas_decode_cag_information_list(®istration_accept->cag_information_list, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE: + size = ogs_nas_decode_truncated_5g_s_tmsi_configuration(®istration_accept->truncated_s_tmsi_configuration, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_TYPE: + size = ogs_nas_decode_wus_assistance_information(®istration_accept->negotiated_wus_assistance_information, pkbuf); + ogs_assert(size >= 0); + registration_accept->presencemask |= OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_registration_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_registration_complete_t *registration_complete = &message->gmm.registration_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode REGISTRATION_COMPLETE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_TYPE: + size = ogs_nas_decode_sor_transparent_container(®istration_complete->sor_transparent_container, pkbuf); + ogs_assert(size >= 0); + registration_complete->presencemask |= OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_registration_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_registration_reject_t *registration_reject = &message->gmm.registration_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode REGISTRATION_REJECT\n"); + + size = ogs_nas_decode_5gmm_cause(®istration_reject->gmm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(®istration_reject->t3346_value, pkbuf); + ogs_assert(size >= 0); + registration_reject->presencemask |= OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(®istration_reject->t3502_value, pkbuf); + ogs_assert(size >= 0); + registration_reject->presencemask |= OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(®istration_reject->eap_message, pkbuf); + ogs_assert(size >= 0); + registration_reject->presencemask |= OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_TYPE: + size = ogs_nas_decode_rejected_nssai(®istration_reject->rejected_nssai, pkbuf); + ogs_assert(size >= 0); + registration_reject->presencemask |= OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_deregistration_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_deregistration_request_from_ue_t *deregistration_request_from_ue = &message->gmm.deregistration_request_from_ue; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DEREGISTRATION_REQUEST\n"); + + size = ogs_nas_decode_de_registration_type(&deregistration_request_from_ue->de_registration_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_5gs_mobile_identity(&deregistration_request_from_ue->mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_deregistration_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_deregistration_request_to_ue_t *deregistration_request_to_ue = &message->gmm.deregistration_request_to_ue; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DEREGISTRATION_REQUEST\n"); + + size = ogs_nas_decode_de_registration_type(&deregistration_request_to_ue->de_registration_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_TYPE: + size = ogs_nas_decode_5gmm_cause(&deregistration_request_to_ue->gmm_cause, pkbuf); + ogs_assert(size >= 0); + deregistration_request_to_ue->presencemask |= OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&deregistration_request_to_ue->t3346_value, pkbuf); + ogs_assert(size >= 0); + deregistration_request_to_ue->presencemask |= OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_TYPE: + size = ogs_nas_decode_rejected_nssai(&deregistration_request_to_ue->rejected_nssai, pkbuf); + ogs_assert(size >= 0); + deregistration_request_to_ue->presencemask |= OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_service_request_t *service_request = &message->gmm.service_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SERVICE_REQUEST\n"); + + size = ogs_nas_decode_key_set_identifier(&service_request->ngksi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_5gs_mobile_identity(&service_request->s_tmsi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_TYPE: + size = ogs_nas_decode_uplink_data_status(&service_request->uplink_data_status, pkbuf); + ogs_assert(size >= 0); + service_request->presencemask |= OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(&service_request->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + service_request->presencemask |= OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_allowed_pdu_session_status(&service_request->allowed_pdu_session_status, pkbuf); + ogs_assert(size >= 0); + service_request->presencemask |= OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_message_container(&service_request->nas_message_container, pkbuf); + ogs_assert(size >= 0); + service_request->presencemask |= OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_service_reject_t *service_reject = &message->gmm.service_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SERVICE_REJECT\n"); + + size = ogs_nas_decode_5gmm_cause(&service_reject->gmm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(&service_reject->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&service_reject->t3346_value, pkbuf); + ogs_assert(size >= 0); + service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&service_reject->eap_message, pkbuf); + ogs_assert(size >= 0); + service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_REJECT_T3448_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&service_reject->t3448_value, pkbuf); + ogs_assert(size >= 0); + service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_T3448_VALUE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_service_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_service_accept_t *service_accept = &message->gmm.service_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SERVICE_ACCEPT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(&service_accept->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + service_accept->presencemask |= OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE: + size = ogs_nas_decode_pdu_session_reactivation_result(&service_accept->pdu_session_reactivation_result, pkbuf); + ogs_assert(size >= 0); + service_accept->presencemask |= OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE: + size = ogs_nas_decode_pdu_session_reactivation_result_error_cause(&service_accept->pdu_session_reactivation_result_error_cause, pkbuf); + ogs_assert(size >= 0); + service_accept->presencemask |= OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&service_accept->eap_message, pkbuf); + ogs_assert(size >= 0); + service_accept->presencemask |= OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&service_accept->t3448_value, pkbuf); + ogs_assert(size >= 0); + service_accept->presencemask |= OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_configuration_update_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_configuration_update_command_t *configuration_update_command = &message->gmm.configuration_update_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode CONFIGURATION_UPDATE_COMMAND\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_TYPE: + size = ogs_nas_decode_configuration_update_indication(&configuration_update_command->configuration_update_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_TYPE: + size = ogs_nas_decode_5gs_mobile_identity(&configuration_update_command->guti, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_TYPE: + size = ogs_nas_decode_5gs_tracking_area_identity_list(&configuration_update_command->tai_list, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_TYPE: + size = ogs_nas_decode_nssai(&configuration_update_command->allowed_nssai, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_TYPE: + size = ogs_nas_decode_service_area_list(&configuration_update_command->service_area_list, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_TYPE: + size = ogs_nas_decode_network_name(&configuration_update_command->full_name_for_network, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_TYPE: + size = ogs_nas_decode_network_name(&configuration_update_command->short_name_for_network, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_TYPE: + size = ogs_nas_decode_time_zone(&configuration_update_command->local_time_zone, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE: + size = ogs_nas_decode_time_zone_and_time(&configuration_update_command->universal_time_and_local_time_zone, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_TYPE: + size = ogs_nas_decode_daylight_saving_time(&configuration_update_command->network_daylight_saving_time, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_TYPE: + size = ogs_nas_decode_ladn_information(&configuration_update_command->ladn_information, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_TYPE: + size = ogs_nas_decode_mico_indication(&configuration_update_command->mico_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_TYPE: + size = ogs_nas_decode_network_slicing_indication(&configuration_update_command->network_slicing_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_TYPE: + size = ogs_nas_decode_nssai(&configuration_update_command->configured_nssai, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_TYPE: + size = ogs_nas_decode_rejected_nssai(&configuration_update_command->rejected_nssai, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE: + size = ogs_nas_decode_operator_defined_access_category_definitions(&configuration_update_command->operator_defined_access_category_definitions, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_TYPE: + size = ogs_nas_decode_sms_indication(&configuration_update_command->sms_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&configuration_update_command->t3447_value, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_TYPE: + size = ogs_nas_decode_cag_information_list(&configuration_update_command->cag_information_list, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_TYPE: + size = ogs_nas_decode_ue_radio_capability_id(&configuration_update_command->ue_radio_capability_id, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE: + size = ogs_nas_decode_ue_radio_capability_id_deletion_indication(&configuration_update_command->ue_radio_capability_id_deletion_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_TYPE: + size = ogs_nas_decode_5gs_registration_result(&configuration_update_command->registration_result, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE: + size = ogs_nas_decode_truncated_5g_s_tmsi_configuration(&configuration_update_command->truncated_s_tmsi_configuration, pkbuf); + ogs_assert(size >= 0); + configuration_update_command->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_configuration_update_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_configuration_update_complete_t *configuration_update_complete = &message->gmm.configuration_update_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode CONFIGURATION_UPDATE_COMPLETE\n"); + + size = ogs_nas_decode_control_plane_service_type(&configuration_update_complete->control_plane_service_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_TYPE: + size = ogs_nas_decode_ciot_small_data_container(&configuration_update_complete->ciot_small_data_container, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_TYPE: + size = ogs_nas_decode_payload_container_type(&configuration_update_complete->payload_container_type, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE: + size = ogs_nas_decode_payload_container(&configuration_update_complete->payload_container, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(&configuration_update_complete->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_TYPE: + size = ogs_nas_decode_release_assistance_indication(&configuration_update_complete->release_assistance_indication, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_TYPE: + size = ogs_nas_decode_uplink_data_status(&configuration_update_complete->uplink_data_status, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_message_container(&configuration_update_complete->nas_message_container, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&configuration_update_complete->additional_information, pkbuf); + ogs_assert(size >= 0); + configuration_update_complete->presencemask |= OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_request_t *authentication_request = &message->gmm.authentication_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_REQUEST\n"); + + size = ogs_nas_decode_key_set_identifier(&authentication_request->ngksi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_abba(&authentication_request->abba, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_TYPE: + size = ogs_nas_decode_authentication_parameter_rand(&authentication_request->authentication_parameter_rand, pkbuf); + ogs_assert(size >= 0); + authentication_request->presencemask |= OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_PRESENT; + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_TYPE: + size = ogs_nas_decode_authentication_parameter_autn(&authentication_request->authentication_parameter_autn, pkbuf); + ogs_assert(size >= 0); + authentication_request->presencemask |= OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_PRESENT; + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&authentication_request->eap_message, pkbuf); + ogs_assert(size >= 0); + authentication_request->presencemask |= OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_response_t *authentication_response = &message->gmm.authentication_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_RESPONSE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_TYPE: + size = ogs_nas_decode_authentication_response_parameter(&authentication_response->authentication_response_parameter, pkbuf); + ogs_assert(size >= 0); + authentication_response->presencemask |= OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_PRESENT; + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&authentication_response->eap_message, pkbuf); + ogs_assert(size >= 0); + authentication_response->presencemask |= OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_reject_t *authentication_reject = &message->gmm.authentication_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_REJECT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&authentication_reject->eap_message, pkbuf); + ogs_assert(size >= 0); + authentication_reject->presencemask |= OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_failure_t *authentication_failure = &message->gmm.authentication_failure; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_FAILURE\n"); + + size = ogs_nas_decode_5gmm_cause(&authentication_failure->gmm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE: + size = ogs_nas_decode_authentication_failure_parameter(&authentication_failure->authentication_failure_parameter, pkbuf); + ogs_assert(size >= 0); + authentication_failure->presencemask |= OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_result(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_result_t *authentication_result = &message->gmm.authentication_result; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_RESULT\n"); + + size = ogs_nas_decode_key_set_identifier(&authentication_result->ngksi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eap_message(&authentication_result->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_AUTHENTICATION_RESULT_ABBA_TYPE: + size = ogs_nas_decode_abba(&authentication_result->abba, pkbuf); + ogs_assert(size >= 0); + authentication_result->presencemask |= OGS_NAS_AUTHENTICATION_RESULT_ABBA_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_identity_request_t *identity_request = &message->gmm.identity_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode IDENTITY_REQUEST\n"); + + size = ogs_nas_decode_5gs_identity_type(&identity_request->identity_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_identity_response_t *identity_response = &message->gmm.identity_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode IDENTITY_RESPONSE\n"); + + size = ogs_nas_decode_5gs_mobile_identity(&identity_response->mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_command_t *security_mode_command = &message->gmm.security_mode_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_COMMAND\n"); + + size = ogs_nas_decode_security_algorithms(&security_mode_command->selected_nas_security_algorithms, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_key_set_identifier(&security_mode_command->ngksi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_ue_security_capability(&security_mode_command->replayed_ue_security_capabilities, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE: + size = ogs_nas_decode_imeisv_request(&security_mode_command->imeisv_request, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_TYPE: + size = ogs_nas_decode_eps_nas_security_algorithms(&security_mode_command->selected_eps_nas_security_algorithms, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_TYPE: + size = ogs_nas_decode_additional_5g_security_information(&security_mode_command->additional_security_information, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&security_mode_command->eap_message, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_ABBA_TYPE: + size = ogs_nas_decode_abba(&security_mode_command->abba, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_ABBA_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_TYPE: + size = ogs_nas_decode_s1_ue_security_capability(&security_mode_command->replayed_s1_ue_security_capabilities, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_complete_t *security_mode_complete = &message->gmm.security_mode_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_COMPLETE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE: + size = ogs_nas_decode_5gs_mobile_identity(&security_mode_complete->imeisv, pkbuf); + ogs_assert(size >= 0); + security_mode_complete->presencemask |= OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_message_container(&security_mode_complete->nas_message_container, pkbuf); + ogs_assert(size >= 0); + security_mode_complete->presencemask |= OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_TYPE: + size = ogs_nas_decode_5gs_mobile_identity(&security_mode_complete->non_imeisv_pei, pkbuf); + ogs_assert(size >= 0); + security_mode_complete->presencemask |= OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_reject_t *security_mode_reject = &message->gmm.security_mode_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_REJECT\n"); + + size = ogs_nas_decode_5gmm_cause(&security_mode_reject->gmm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_5gmm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_5gmm_status_t *gmm_status = &message->gmm.gmm_status; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode 5GMM_STATUS\n"); + + size = ogs_nas_decode_5gmm_cause(&gmm_status->gmm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_notification_t *notification = &message->gmm.notification; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode NOTIFICATION\n"); + + size = ogs_nas_decode_access_type(¬ification->access_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_notification_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_notification_response_t *notification_response = &message->gmm.notification_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode NOTIFICATION_RESPONSE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(¬ification_response->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + notification_response->presencemask |= OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_ul_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_ul_nas_transport_t *ul_nas_transport = &message->gmm.ul_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode UL_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_payload_container_type(&ul_nas_transport->payload_container_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_payload_container(&ul_nas_transport->payload_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_TYPE: + size = ogs_nas_decode_pdu_session_identity_2(&ul_nas_transport->old_pdu_session_id, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_TYPE: + size = ogs_nas_decode_request_type(&ul_nas_transport->request_type, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_TYPE: + size = ogs_nas_decode_s_nssai(&ul_nas_transport->s_nssai, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_DNN_TYPE: + size = ogs_nas_decode_dnn(&ul_nas_transport->dnn, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_DNN_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&ul_nas_transport->additional_information, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_TYPE: + size = ogs_nas_decode_ma_pdu_session_information(&ul_nas_transport->ma_pdu_session_information, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_TYPE: + size = ogs_nas_decode_release_assistance_indication(&ul_nas_transport->release_assistance_indication, pkbuf); + ogs_assert(size >= 0); + ul_nas_transport->presencemask |= OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_dl_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_dl_nas_transport_t *dl_nas_transport = &message->gmm.dl_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DL_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_payload_container_type(&dl_nas_transport->payload_container_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_payload_container(&dl_nas_transport->payload_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&dl_nas_transport->additional_information, pkbuf); + ogs_assert(size >= 0); + dl_nas_transport->presencemask |= OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + case OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_TYPE: + size = ogs_nas_decode_5gmm_cause(&dl_nas_transport->gmm_cause, pkbuf); + ogs_assert(size >= 0); + dl_nas_transport->presencemask |= OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&dl_nas_transport->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + dl_nas_transport->presencemask |= OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_establishment_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_establishment_request_t *pdu_session_establishment_request = &message->gsm.pdu_session_establishment_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_ESTABLISHMENT_REQUEST\n"); + + size = ogs_nas_decode_control_plane_service_type(&pdu_session_establishment_request->control_plane_service_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_TYPE: + size = ogs_nas_decode_ciot_small_data_container(&pdu_session_establishment_request->ciot_small_data_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE: + size = ogs_nas_decode_payload_container_type(&pdu_session_establishment_request->payload_container_type, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE: + size = ogs_nas_decode_payload_container(&pdu_session_establishment_request->payload_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_TYPE: + size = ogs_nas_decode_pdu_session_status(&pdu_session_establishment_request->pdu_session_status, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_TYPE: + size = ogs_nas_decode_release_assistance_indication(&pdu_session_establishment_request->release_assistance_indication, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_TYPE: + size = ogs_nas_decode_uplink_data_status(&pdu_session_establishment_request->uplink_data_status, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_message_container(&pdu_session_establishment_request->nas_message_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&pdu_session_establishment_request->additional_information, pkbuf); + ogs_assert(size >= 0); + pdu_session_establishment_request->presencemask |= OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_establishment_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_establishment_accept_t *pdu_session_establishment_accept = &message->gsm.pdu_session_establishment_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_ESTABLISHMENT_ACCEPT\n"); + + size = ogs_nas_decode_s_nssai(&pdu_session_establishment_accept->s_nssai, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eap_message(&pdu_session_establishment_accept->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_pdu_session_establishment_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_establishment_reject_t *pdu_session_establishment_reject = &message->gsm.pdu_session_establishment_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_ESTABLISHMENT_REJECT\n"); + + size = ogs_nas_decode_s_nssai(&pdu_session_establishment_reject->s_nssai, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eap_message(&pdu_session_establishment_reject->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_pdu_session_authentication_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_authentication_command_t *pdu_session_authentication_command = &message->gsm.pdu_session_authentication_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_AUTHENTICATION_COMMAND\n"); + + size = ogs_nas_decode_s_nssai(&pdu_session_authentication_command->s_nssai, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eap_message(&pdu_session_authentication_command->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_pdu_session_authentication_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_authentication_complete_t *pdu_session_authentication_complete = &message->gsm.pdu_session_authentication_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_AUTHENTICATION_COMPLETE\n"); + + size = ogs_nas_decode_integrity_protection_maximum_data_rate(&pdu_session_authentication_complete->integrity_protection_maximum_data_rate, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_TYPE: + size = ogs_nas_decode_pdu_session_type(&pdu_session_authentication_complete->pdu_session_type, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_TYPE: + size = ogs_nas_decode_ssc_mode(&pdu_session_authentication_complete->ssc_mode, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_TYPE: + size = ogs_nas_decode_5gsm_capability(&pdu_session_authentication_complete->gsm_capability, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE: + size = ogs_nas_decode_maximum_number_of_supported_packet_filters(&pdu_session_authentication_complete->maximum_number_of_supported_packet_filters, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE: + size = ogs_nas_decode_always_on_pdu_session_requested(&pdu_session_authentication_complete->always_on_pdu_session_requested, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_TYPE: + size = ogs_nas_decode_sm_pdu_dn_request_container(&pdu_session_authentication_complete->sm_pdu_dn_request_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_authentication_complete->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&pdu_session_authentication_complete->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_TYPE: + size = ogs_nas_decode_ds_tt_ethernet_port_mac_address(&pdu_session_authentication_complete->ds_tt_ethernet_port_mac_address, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_TYPE: + size = ogs_nas_decode_ue_ds_tt_residence_time(&pdu_session_authentication_complete->ue_ds_tt_residence_time, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE: + size = ogs_nas_decode_port_management_information_container(&pdu_session_authentication_complete->port_management_information_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_complete->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_authentication_result(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_authentication_result_t *pdu_session_authentication_result = &message->gsm.pdu_session_authentication_result; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_AUTHENTICATION_RESULT\n"); + + size = ogs_nas_decode_pdu_session_type(&pdu_session_authentication_result->selected_pdu_session_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_qos_rules(&pdu_session_authentication_result->authorized_qos_rules, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_session_ambr(&pdu_session_authentication_result->session_ambr, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_TYPE: + size = ogs_nas_decode_5gsm_cause(&pdu_session_authentication_result->gsm_cause, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_TYPE: + size = ogs_nas_decode_pdu_address(&pdu_session_authentication_result->pdu_address, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&pdu_session_authentication_result->rq_timer_value, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_TYPE: + size = ogs_nas_decode_s_nssai(&pdu_session_authentication_result->s_nssai, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE: + size = ogs_nas_decode_always_on_pdu_session_indication(&pdu_session_authentication_result->always_on_pdu_session_indication, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_TYPE: + size = ogs_nas_decode_mapped_eps_bearer_contexts(&pdu_session_authentication_result->mapped_eps_bearer_contexts, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&pdu_session_authentication_result->eap_message, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE: + size = ogs_nas_decode_qos_flow_descriptions(&pdu_session_authentication_result->authorized_qos_flow_descriptions, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_authentication_result->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_TYPE: + size = ogs_nas_decode_dnn(&pdu_session_authentication_result->dnn, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_5gsm_network_feature_support(&pdu_session_authentication_result->gsm_network_feature_support, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_TYPE: + size = ogs_nas_decode_serving_plmn_rate_control(&pdu_session_authentication_result->serving_plmn_rate_control, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_TYPE: + size = ogs_nas_decode_atsss_container(&pdu_session_authentication_result->atsss_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_TYPE: + size = ogs_nas_decode_control_plane_only_indication(&pdu_session_authentication_result->control_plane_only_indication, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&pdu_session_authentication_result->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + pdu_session_authentication_result->presencemask |= OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_modification_request_t *pdu_session_modification_request = &message->gsm.pdu_session_modification_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_MODIFICATION_REQUEST\n"); + + size = ogs_nas_decode_5gsm_cause(&pdu_session_modification_request->gsm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&pdu_session_modification_request->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_TYPE: + size = ogs_nas_decode_allowed_ssc_mode(&pdu_session_modification_request->allowed_ssc_mode, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&pdu_session_modification_request->eap_message, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_modification_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_re_attempt_indicator(&pdu_session_modification_request->re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_5gsm_congestion_re_attempt_indicator(&pdu_session_modification_request->gsm_congestion_re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_request->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_modification_reject_t *pdu_session_modification_reject = &message->gsm.pdu_session_modification_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_MODIFICATION_REJECT\n"); + + size = ogs_nas_decode_eap_message(&pdu_session_modification_reject->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_modification_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_modification_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_modification_command_t *pdu_session_modification_command = &message->gsm.pdu_session_modification_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_MODIFICATION_COMMAND\n"); + + size = ogs_nas_decode_eap_message(&pdu_session_modification_command->eap_message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_modification_command->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_modification_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_modification_complete_t *pdu_session_modification_complete = &message->gsm.pdu_session_modification_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_MODIFICATION_COMPLETE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_TYPE: + size = ogs_nas_decode_eap_message(&pdu_session_modification_complete->eap_message, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_complete->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_modification_complete->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_complete->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_modification_command_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_modification_command_reject_t *pdu_session_modification_command_reject = &message->gsm.pdu_session_modification_command_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_MODIFICATION_COMMAND_REJECT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_TYPE: + size = ogs_nas_decode_5gsm_capability(&pdu_session_modification_command_reject->gsm_capability, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_TYPE: + size = ogs_nas_decode_5gsm_cause(&pdu_session_modification_command_reject->gsm_cause, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE: + size = ogs_nas_decode_maximum_number_of_supported_packet_filters(&pdu_session_modification_command_reject->maximum_number_of_supported_packet_filters, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE: + size = ogs_nas_decode_always_on_pdu_session_requested(&pdu_session_modification_command_reject->always_on_pdu_session_requested, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_TYPE: + size = ogs_nas_decode_integrity_protection_maximum_data_rate(&pdu_session_modification_command_reject->integrity_protection_maximum_data_rate, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_TYPE: + size = ogs_nas_decode_qos_rules(&pdu_session_modification_command_reject->requested_qos_rules, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_TYPE: + size = ogs_nas_decode_qos_flow_descriptions(&pdu_session_modification_command_reject->requested_qos_flow_descriptions, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE: + size = ogs_nas_decode_mapped_eps_bearer_contexts(&pdu_session_modification_command_reject->mapped_eps_bearer_contexts, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_modification_command_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE: + size = ogs_nas_decode_port_management_information_container(&pdu_session_modification_command_reject->port_management_information_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&pdu_session_modification_command_reject->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + pdu_session_modification_command_reject->presencemask |= OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_release_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_release_request_t *pdu_session_release_request = &message->gsm.pdu_session_release_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_RELEASE_REQUEST\n"); + + size = ogs_nas_decode_5gsm_cause(&pdu_session_release_request->gsm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&pdu_session_release_request->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_request->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_release_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_request->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_re_attempt_indicator(&pdu_session_release_request->re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_request->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_5gsm_congestion_re_attempt_indicator(&pdu_session_release_request->gsm_congestion_re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_request->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_release_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_release_reject_t *pdu_session_release_reject = &message->gsm.pdu_session_release_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_RELEASE_REJECT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_TYPE: + size = ogs_nas_decode_5gsm_cause(&pdu_session_release_reject->gsm_cause, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_TYPE: + size = ogs_nas_decode_session_ambr(&pdu_session_release_reject->session_ambr, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&pdu_session_release_reject->rq_timer_value, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE: + size = ogs_nas_decode_always_on_pdu_session_indication(&pdu_session_release_reject->always_on_pdu_session_indication, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_TYPE: + size = ogs_nas_decode_qos_rules(&pdu_session_release_reject->authorized_qos_rules, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE: + size = ogs_nas_decode_mapped_eps_bearer_contexts(&pdu_session_release_reject->mapped_eps_bearer_contexts, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE: + size = ogs_nas_decode_qos_flow_descriptions(&pdu_session_release_reject->authorized_qos_flow_descriptions, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_release_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_TYPE: + size = ogs_nas_decode_atsss_container(&pdu_session_release_reject->atsss_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&pdu_session_release_reject->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE: + size = ogs_nas_decode_port_management_information_container(&pdu_session_release_reject->port_management_information_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_TYPE: + size = ogs_nas_decode_serving_plmn_rate_control(&pdu_session_release_reject->serving_plmn_rate_control, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_reject->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_release_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_release_command_t *pdu_session_release_command = &message->gsm.pdu_session_release_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_RELEASE_COMMAND\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_release_command->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_command->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE: + size = ogs_nas_decode_port_management_information_container(&pdu_session_release_command->port_management_information_container, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_command->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdu_session_release_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdu_session_release_complete_t *pdu_session_release_complete = &message->gsm.pdu_session_release_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDU_SESSION_RELEASE_COMPLETE\n"); + + size = ogs_nas_decode_5gsm_cause(&pdu_session_release_complete->gsm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdu_session_release_complete->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdu_session_release_complete->presencemask |= OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_5gsm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_5gsm_status_t *gsm_status = &message->gsm.gsm_status; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode 5GSM_STATUS\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { + case OGS_NAS_5GSM_STATUS_5GSM_CAUSE_TYPE: + size = ogs_nas_decode_5gsm_cause(&gsm_status->gsm_cause, pkbuf); + ogs_assert(size >= 0); + gsm_status->presencemask |= OGS_NAS_5GSM_STATUS_5GSM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&gsm_status->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + gsm_status->presencemask |= OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_5gmm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_5gmm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->gmm.h, pkbuf->data - size, size); + decoded += size; + + switch(message->gmm.h.message_type) { + case OGS_NAS_REGISTRATION_REQUEST: + size = ogs_nas_decode_registration_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT: + size = ogs_nas_decode_registration_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_REGISTRATION_COMPLETE: + size = ogs_nas_decode_registration_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_REGISTRATION_REJECT: + size = ogs_nas_decode_registration_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DEREGISTRATION_REQUEST: + size = ogs_nas_decode_deregistration_request_from_ue(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DEREGISTRATION_ACCEPT: + break; + case OGS_NAS_SERVICE_REQUEST: + size = ogs_nas_decode_service_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SERVICE_REJECT: + size = ogs_nas_decode_service_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT: + size = ogs_nas_decode_service_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND: + size = ogs_nas_decode_configuration_update_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE: + size = ogs_nas_decode_configuration_update_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_REQUEST: + size = ogs_nas_decode_authentication_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESPONSE: + size = ogs_nas_decode_authentication_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_REJECT: + size = ogs_nas_decode_authentication_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_FAILURE: + size = ogs_nas_decode_authentication_failure(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESULT: + size = ogs_nas_decode_authentication_result(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_IDENTITY_REQUEST: + size = ogs_nas_decode_identity_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_IDENTITY_RESPONSE: + size = ogs_nas_decode_identity_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND: + size = ogs_nas_decode_security_mode_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE: + size = ogs_nas_decode_security_mode_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_REJECT: + size = ogs_nas_decode_security_mode_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_5GMM_STATUS: + size = ogs_nas_decode_5gmm_status(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_NOTIFICATION: + size = ogs_nas_decode_notification(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_NOTIFICATION_RESPONSE: + size = ogs_nas_decode_notification_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT: + size = ogs_nas_decode_ul_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DL_NAS_TRANSPORT: + size = ogs_nas_decode_dl_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gmm.h.message_type); + break; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} +int ogs_nas_5gsm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_5gsm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->gsm.h, pkbuf->data - size, size); + decoded += size; + + switch(message->gsm.h.message_type) { + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST: + size = ogs_nas_decode_pdu_session_establishment_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_ACCEPT: + size = ogs_nas_decode_pdu_session_establishment_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REJECT: + size = ogs_nas_decode_pdu_session_establishment_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMMAND: + size = ogs_nas_decode_pdu_session_authentication_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE: + size = ogs_nas_decode_pdu_session_authentication_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT: + size = ogs_nas_decode_pdu_session_authentication_result(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST: + size = ogs_nas_decode_pdu_session_modification_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REJECT: + size = ogs_nas_decode_pdu_session_modification_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND: + size = ogs_nas_decode_pdu_session_modification_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE: + size = ogs_nas_decode_pdu_session_modification_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT: + size = ogs_nas_decode_pdu_session_modification_command_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST: + size = ogs_nas_decode_pdu_session_release_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT: + size = ogs_nas_decode_pdu_session_release_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_COMMAND: + size = ogs_nas_decode_pdu_session_release_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_COMPLETE: + size = ogs_nas_decode_pdu_session_release_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_5GSM_STATUS: + size = ogs_nas_decode_5gsm_status(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gsm.h.message_type); + break; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} + diff --git a/lib/nas/5gs/encoder.c b/lib/nas/5gs/encoder.c new file mode 100644 index 000000000..b7cc5694a --- /dev/null +++ b/lib/nas/5gs/encoder.c @@ -0,0 +1,3187 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 21:20:09.052256 by acetcom + * from 24501-g41.docx + ******************************************************************************/ + +#include "ogs-nas-5gs.h" + +int ogs_nas_encode_registration_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_registration_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_registration_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_registration_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_deregistration_request_from_ue(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_deregistration_request_to_ue(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_service_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_service_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_service_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_configuration_update_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_configuration_update_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_authentication_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_authentication_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_authentication_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_authentication_failure(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_authentication_result(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_identity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_identity_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_security_mode_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_security_mode_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_security_mode_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_5gmm_status(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_notification_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_ul_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_dl_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_establishment_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_establishment_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_establishment_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_authentication_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_authentication_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_authentication_result(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_modification_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_modification_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_modification_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_modification_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_modification_command_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_release_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_release_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_release_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_pdu_session_release_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_5gsm_status(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); +int ogs_nas_encode_registration_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_registration_request_t *registration_request = &message->gmm.registration_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode REGISTRATION_REQUEST"); + + size = ogs_nas_encode_5gs_registration_type(pkbuf, ®istration_request->registration_type); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, ®istration_request->mobile_identity); + ogs_assert(size >= 0); + encoded += size; + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT) { + registration_request->non_current_native_nas_key_set_identifier.type = (OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE >> 4); + + size = ogs_nas_encode_key_set_identifier(pkbuf, ®istration_request->non_current_native_nas_key_set_identifier); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gmm_capability(pkbuf, ®istration_request->gmm_capability); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_security_capability(pkbuf, ®istration_request->ue_security_capability); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, ®istration_request->requested_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_tracking_area_identity(pkbuf, ®istration_request->last_visited_registered_tai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_s1_ue_network_capability(pkbuf, ®istration_request->s1_ue_network_capability); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_uplink_data_status(pkbuf, ®istration_request->uplink_data_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, ®istration_request->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_PRESENT) { + registration_request->mico_indication.type = (OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_mico_indication(pkbuf, ®istration_request->mico_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_status(pkbuf, ®istration_request->ue_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, ®istration_request->additional_guti); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_allowed_pdu_session_status(pkbuf, ®istration_request->allowed_pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_usage_setting(pkbuf, ®istration_request->ue_usage_setting); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_drx_parameters(pkbuf, ®istration_request->requested_drx_parameters); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eps_nas_message_container(pkbuf, ®istration_request->eps_nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ladn_indication(pkbuf, ®istration_request->ladn_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT) { + registration_request->payload_container_type.type = (OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE >> 4); + + size = ogs_nas_encode_payload_container_type(pkbuf, ®istration_request->payload_container_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_payload_container(pkbuf, ®istration_request->payload_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_PRESENT) { + registration_request->network_slicing_indication.type = (OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_network_slicing_indication(pkbuf, ®istration_request->network_slicing_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_update_type(pkbuf, ®istration_request->update_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_mobile_station_classmark_2(pkbuf, ®istration_request->mobile_station_classmark_2); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_supported_codec_list(pkbuf, ®istration_request->supported_codecs); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_message_container(pkbuf, ®istration_request->nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eps_bearer_context_status(pkbuf, ®istration_request->eps_bearer_context_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_drx_parameters(pkbuf, ®istration_request->requested_extended_drx_parameters); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, ®istration_request->t3324_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_radio_capability_id(pkbuf, ®istration_request->ue_radio_capability_id); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_mapped_nssai(pkbuf, ®istration_request->requested_mapped_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_information_requested(pkbuf, ®istration_request->additional_information_requested); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_wus_assistance_information(pkbuf, ®istration_request->requested_wus_assistance_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_request->presencemask & OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_PRESENT) { + registration_request->n5gc_indication.type = OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_TYPE; + + size = ogs_nas_encode_n5gc_indication(pkbuf, ®istration_request->n5gc_indication); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_registration_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_registration_accept_t *registration_accept = &message->gmm.registration_accept; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode REGISTRATION_ACCEPT"); + + size = ogs_nas_encode_5gs_registration_result(pkbuf, ®istration_accept->registration_result); + ogs_assert(size >= 0); + encoded += size; + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, ®istration_accept->guti); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_plmn_list(pkbuf, ®istration_accept->equivalent_plmns); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_tracking_area_identity_list(pkbuf, ®istration_accept->tai_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, ®istration_accept->allowed_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_rejected_nssai(pkbuf, ®istration_accept->rejected_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, ®istration_accept->configured_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_network_feature_support(pkbuf, ®istration_accept->network_feature_support); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, ®istration_accept->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_reactivation_result(pkbuf, ®istration_accept->pdu_session_reactivation_result); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_reactivation_result_error_cause(pkbuf, ®istration_accept->pdu_session_reactivation_result_error_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ladn_information(pkbuf, ®istration_accept->ladn_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_PRESENT) { + registration_accept->mico_indication.type = (OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_mico_indication(pkbuf, ®istration_accept->mico_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_PRESENT) { + registration_accept->network_slicing_indication.type = (OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_network_slicing_indication(pkbuf, ®istration_accept->network_slicing_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_service_area_list(pkbuf, ®istration_accept->service_area_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, ®istration_accept->t3512_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, ®istration_accept->non_3gpp_de_registration_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, ®istration_accept->t3502_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_emergency_number_list(pkbuf, ®istration_accept->emergency_number_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_emergency_number_list(pkbuf, ®istration_accept->extended_emergency_number_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_sor_transparent_container(pkbuf, ®istration_accept->sor_transparent_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, ®istration_accept->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_PRESENT) { + registration_accept->nssai_inclusion_mode.type = (OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_TYPE >> 4); + + size = ogs_nas_encode_nssai_inclusion_mode(pkbuf, ®istration_accept->nssai_inclusion_mode); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_operator_defined_access_category_definitions(pkbuf, ®istration_accept->operator_defined_access_category_definitions); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_drx_parameters(pkbuf, ®istration_accept->negotiated_drx_parameters); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_PRESENT) { + registration_accept->non_3gpp_nw_policies.type = (OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_TYPE >> 4); + + size = ogs_nas_encode_non_3gpp_nw_provided_policies(pkbuf, ®istration_accept->non_3gpp_nw_policies); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eps_bearer_context_status(pkbuf, ®istration_accept->eps_bearer_context_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_drx_parameters(pkbuf, ®istration_accept->negotiated_extended_drx_parameters); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, ®istration_accept->t3447_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, ®istration_accept->t3448_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, ®istration_accept->t3324_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_radio_capability_id(pkbuf, ®istration_accept->ue_radio_capability_id); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT) { + registration_accept->ue_radio_capability_id_deletion_indication.type = (OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_ue_radio_capability_id_deletion_indication(pkbuf, ®istration_accept->ue_radio_capability_id_deletion_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, ®istration_accept->pending_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ciphering_key_data(pkbuf, ®istration_accept->ciphering_key_data); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_cag_information_list(pkbuf, ®istration_accept->cag_information_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_truncated_5g_s_tmsi_configuration(pkbuf, ®istration_accept->truncated_s_tmsi_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_accept->presencemask & OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_wus_assistance_information(pkbuf, ®istration_accept->negotiated_wus_assistance_information); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_registration_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_registration_complete_t *registration_complete = &message->gmm.registration_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode REGISTRATION_COMPLETE"); + + if (registration_complete->presencemask & OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_sor_transparent_container(pkbuf, ®istration_complete->sor_transparent_container); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_registration_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_registration_reject_t *registration_reject = &message->gmm.registration_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode REGISTRATION_REJECT"); + + size = ogs_nas_encode_5gmm_cause(pkbuf, ®istration_reject->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (registration_reject->presencemask & OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, ®istration_reject->t3346_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_reject->presencemask & OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, ®istration_reject->t3502_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_reject->presencemask & OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, ®istration_reject->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (registration_reject->presencemask & OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_rejected_nssai(pkbuf, ®istration_reject->rejected_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_deregistration_request_from_ue(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_deregistration_request_from_ue_t *deregistration_request_from_ue = &message->gmm.deregistration_request_from_ue; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode DEREGISTRATION_REQUEST"); + + size = ogs_nas_encode_de_registration_type(pkbuf, &deregistration_request_from_ue->de_registration_type); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &deregistration_request_from_ue->mobile_identity); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_deregistration_request_to_ue(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_deregistration_request_to_ue_t *deregistration_request_to_ue = &message->gmm.deregistration_request_to_ue; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode DEREGISTRATION_REQUEST"); + + size = ogs_nas_encode_de_registration_type(pkbuf, &deregistration_request_to_ue->de_registration_type); + ogs_assert(size >= 0); + encoded += size; + + if (deregistration_request_to_ue->presencemask & OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gmm_cause(pkbuf, &deregistration_request_to_ue->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (deregistration_request_to_ue->presencemask & OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, &deregistration_request_to_ue->t3346_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (deregistration_request_to_ue->presencemask & OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_rejected_nssai(pkbuf, &deregistration_request_to_ue->rejected_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_service_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_service_request_t *service_request = &message->gmm.service_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SERVICE_REQUEST"); + + size = ogs_nas_encode_key_set_identifier(pkbuf, &service_request->ngksi); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &service_request->s_tmsi); + ogs_assert(size >= 0); + encoded += size; + + if (service_request->presencemask & OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_uplink_data_status(pkbuf, &service_request->uplink_data_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_request->presencemask & OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, &service_request->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_request->presencemask & OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_allowed_pdu_session_status(pkbuf, &service_request->allowed_pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_request->presencemask & OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_message_container(pkbuf, &service_request->nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_service_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_service_reject_t *service_reject = &message->gmm.service_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SERVICE_REJECT"); + + size = ogs_nas_encode_5gmm_cause(pkbuf, &service_reject->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, &service_reject->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_2(pkbuf, &service_reject->t3346_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &service_reject->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_T3448_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REJECT_T3448_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &service_reject->t3448_value); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_service_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_service_accept_t *service_accept = &message->gmm.service_accept; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SERVICE_ACCEPT"); + + if (service_accept->presencemask & OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, &service_accept->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_accept->presencemask & OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_reactivation_result(pkbuf, &service_accept->pdu_session_reactivation_result); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_accept->presencemask & OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_reactivation_result_error_cause(pkbuf, &service_accept->pdu_session_reactivation_result_error_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_accept->presencemask & OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &service_accept->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (service_accept->presencemask & OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &service_accept->t3448_value); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_configuration_update_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_configuration_update_command_t *configuration_update_command = &message->gmm.configuration_update_command; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode CONFIGURATION_UPDATE_COMMAND"); + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_PRESENT) { + configuration_update_command->configuration_update_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_configuration_update_indication(pkbuf, &configuration_update_command->configuration_update_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &configuration_update_command->guti); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_tracking_area_identity_list(pkbuf, &configuration_update_command->tai_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, &configuration_update_command->allowed_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_service_area_list(pkbuf, &configuration_update_command->service_area_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_network_name(pkbuf, &configuration_update_command->full_name_for_network); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_network_name(pkbuf, &configuration_update_command->short_name_for_network); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_time_zone(pkbuf, &configuration_update_command->local_time_zone); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_time_zone_and_time(pkbuf, &configuration_update_command->universal_time_and_local_time_zone); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_daylight_saving_time(pkbuf, &configuration_update_command->network_daylight_saving_time); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ladn_information(pkbuf, &configuration_update_command->ladn_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_PRESENT) { + configuration_update_command->mico_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_mico_indication(pkbuf, &configuration_update_command->mico_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_PRESENT) { + configuration_update_command->network_slicing_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_network_slicing_indication(pkbuf, &configuration_update_command->network_slicing_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_nssai(pkbuf, &configuration_update_command->configured_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_rejected_nssai(pkbuf, &configuration_update_command->rejected_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_operator_defined_access_category_definitions(pkbuf, &configuration_update_command->operator_defined_access_category_definitions); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_PRESENT) { + configuration_update_command->sms_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_sms_indication(pkbuf, &configuration_update_command->sms_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &configuration_update_command->t3447_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_cag_information_list(pkbuf, &configuration_update_command->cag_information_list); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_radio_capability_id(pkbuf, &configuration_update_command->ue_radio_capability_id); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT) { + configuration_update_command->ue_radio_capability_id_deletion_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_ue_radio_capability_id_deletion_indication(pkbuf, &configuration_update_command->ue_radio_capability_id_deletion_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_registration_result(pkbuf, &configuration_update_command->registration_result); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_command->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_truncated_5g_s_tmsi_configuration(pkbuf, &configuration_update_command->truncated_s_tmsi_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_configuration_update_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_configuration_update_complete_t *configuration_update_complete = &message->gmm.configuration_update_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode CONFIGURATION_UPDATE_COMPLETE"); + + size = ogs_nas_encode_control_plane_service_type(pkbuf, &configuration_update_complete->control_plane_service_type); + ogs_assert(size >= 0); + encoded += size; + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ciot_small_data_container(pkbuf, &configuration_update_complete->ciot_small_data_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_PRESENT) { + configuration_update_complete->payload_container_type.type = (OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_TYPE >> 4); + + size = ogs_nas_encode_payload_container_type(pkbuf, &configuration_update_complete->payload_container_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_payload_container(pkbuf, &configuration_update_complete->payload_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, &configuration_update_complete->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_PRESENT) { + configuration_update_complete->release_assistance_indication.type = (OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_release_assistance_indication(pkbuf, &configuration_update_complete->release_assistance_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_uplink_data_status(pkbuf, &configuration_update_complete->uplink_data_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_message_container(pkbuf, &configuration_update_complete->nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (configuration_update_complete->presencemask & OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_information(pkbuf, &configuration_update_complete->additional_information); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_authentication_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_authentication_request_t *authentication_request = &message->gmm.authentication_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode AUTHENTICATION_REQUEST"); + + size = ogs_nas_encode_key_set_identifier(pkbuf, &authentication_request->ngksi); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_abba(pkbuf, &authentication_request->abba); + ogs_assert(size >= 0); + encoded += size; + + if (authentication_request->presencemask & OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_authentication_parameter_rand(pkbuf, &authentication_request->authentication_parameter_rand); + ogs_assert(size >= 0); + encoded += size; + } + + if (authentication_request->presencemask & OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_authentication_parameter_autn(pkbuf, &authentication_request->authentication_parameter_autn); + ogs_assert(size >= 0); + encoded += size; + } + + if (authentication_request->presencemask & OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &authentication_request->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_authentication_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_authentication_response_t *authentication_response = &message->gmm.authentication_response; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode AUTHENTICATION_RESPONSE"); + + if (authentication_response->presencemask & OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_authentication_response_parameter(pkbuf, &authentication_response->authentication_response_parameter); + ogs_assert(size >= 0); + encoded += size; + } + + if (authentication_response->presencemask & OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &authentication_response->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_authentication_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_authentication_reject_t *authentication_reject = &message->gmm.authentication_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode AUTHENTICATION_REJECT"); + + if (authentication_reject->presencemask & OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &authentication_reject->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_authentication_failure(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_authentication_failure_t *authentication_failure = &message->gmm.authentication_failure; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode AUTHENTICATION_FAILURE"); + + size = ogs_nas_encode_5gmm_cause(pkbuf, &authentication_failure->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (authentication_failure->presencemask & OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_authentication_failure_parameter(pkbuf, &authentication_failure->authentication_failure_parameter); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_authentication_result(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_authentication_result_t *authentication_result = &message->gmm.authentication_result; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode AUTHENTICATION_RESULT"); + + size = ogs_nas_encode_key_set_identifier(pkbuf, &authentication_result->ngksi); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &authentication_result->eap_message); + ogs_assert(size >= 0); + encoded += size; + + if (authentication_result->presencemask & OGS_NAS_AUTHENTICATION_RESULT_ABBA_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_RESULT_ABBA_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_abba(pkbuf, &authentication_result->abba); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_identity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_identity_request_t *identity_request = &message->gmm.identity_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode IDENTITY_REQUEST"); + + size = ogs_nas_encode_5gs_identity_type(pkbuf, &identity_request->identity_type); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_identity_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_identity_response_t *identity_response = &message->gmm.identity_response; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode IDENTITY_RESPONSE"); + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &identity_response->mobile_identity); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_security_mode_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_security_mode_command_t *security_mode_command = &message->gmm.security_mode_command; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SECURITY_MODE_COMMAND"); + + size = ogs_nas_encode_security_algorithms(pkbuf, &security_mode_command->selected_nas_security_algorithms); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_key_set_identifier(pkbuf, &security_mode_command->ngksi); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_security_capability(pkbuf, &security_mode_command->replayed_ue_security_capabilities); + ogs_assert(size >= 0); + encoded += size; + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT) { + security_mode_command->imeisv_request.type = (OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE >> 4); + + size = ogs_nas_encode_imeisv_request(pkbuf, &security_mode_command->imeisv_request); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eps_nas_security_algorithms(pkbuf, &security_mode_command->selected_eps_nas_security_algorithms); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_5g_security_information(pkbuf, &security_mode_command->additional_security_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &security_mode_command->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_ABBA_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_ABBA_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_abba(pkbuf, &security_mode_command->abba); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_s1_ue_security_capability(pkbuf, &security_mode_command->replayed_s1_ue_security_capabilities); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_security_mode_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_security_mode_complete_t *security_mode_complete = &message->gmm.security_mode_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SECURITY_MODE_COMPLETE"); + + if (security_mode_complete->presencemask & OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &security_mode_complete->imeisv); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_complete->presencemask & OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_message_container(pkbuf, &security_mode_complete->nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (security_mode_complete->presencemask & OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gs_mobile_identity(pkbuf, &security_mode_complete->non_imeisv_pei); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_security_mode_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_security_mode_reject_t *security_mode_reject = &message->gmm.security_mode_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode SECURITY_MODE_REJECT"); + + size = ogs_nas_encode_5gmm_cause(pkbuf, &security_mode_reject->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_5gmm_status(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_5gmm_status_t *gmm_status = &message->gmm.gmm_status; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode 5GMM_STATUS"); + + size = ogs_nas_encode_5gmm_cause(pkbuf, &gmm_status->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_notification_t *notification = &message->gmm.notification; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode NOTIFICATION"); + + size = ogs_nas_encode_access_type(pkbuf, ¬ification->access_type); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_notification_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_notification_response_t *notification_response = &message->gmm.notification_response; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode NOTIFICATION_RESPONSE"); + + if (notification_response->presencemask & OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, ¬ification_response->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_ul_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_ul_nas_transport_t *ul_nas_transport = &message->gmm.ul_nas_transport; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode UL_NAS_TRANSPORT"); + + size = ogs_nas_encode_payload_container_type(pkbuf, &ul_nas_transport->payload_container_type); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_payload_container(pkbuf, &ul_nas_transport->payload_container); + ogs_assert(size >= 0); + encoded += size; + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_identity_2(pkbuf, &ul_nas_transport->old_pdu_session_id); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_PRESENT) { + ul_nas_transport->request_type.type = (OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_TYPE >> 4); + + size = ogs_nas_encode_request_type(pkbuf, &ul_nas_transport->request_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_s_nssai(pkbuf, &ul_nas_transport->s_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_DNN_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_UL_NAS_TRANSPORT_DNN_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_dnn(pkbuf, &ul_nas_transport->dnn); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_information(pkbuf, &ul_nas_transport->additional_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_PRESENT) { + ul_nas_transport->ma_pdu_session_information.type = (OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_TYPE >> 4); + + size = ogs_nas_encode_ma_pdu_session_information(pkbuf, &ul_nas_transport->ma_pdu_session_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (ul_nas_transport->presencemask & OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_PRESENT) { + ul_nas_transport->release_assistance_indication.type = (OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_release_assistance_indication(pkbuf, &ul_nas_transport->release_assistance_indication); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_dl_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_dl_nas_transport_t *dl_nas_transport = &message->gmm.dl_nas_transport; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode DL_NAS_TRANSPORT"); + + size = ogs_nas_encode_payload_container_type(pkbuf, &dl_nas_transport->payload_container_type); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_payload_container(pkbuf, &dl_nas_transport->payload_container); + ogs_assert(size >= 0); + encoded += size; + + if (dl_nas_transport->presencemask & OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_information(pkbuf, &dl_nas_transport->additional_information); + ogs_assert(size >= 0); + encoded += size; + } + + if (dl_nas_transport->presencemask & OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gmm_cause(pkbuf, &dl_nas_transport->gmm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (dl_nas_transport->presencemask & OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &dl_nas_transport->back_off_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_establishment_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_establishment_request_t *pdu_session_establishment_request = &message->gsm.pdu_session_establishment_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_ESTABLISHMENT_REQUEST"); + + size = ogs_nas_encode_control_plane_service_type(pkbuf, &pdu_session_establishment_request->control_plane_service_type); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ciot_small_data_container(pkbuf, &pdu_session_establishment_request->ciot_small_data_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT) { + pdu_session_establishment_request->payload_container_type.type = (OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE >> 4); + + size = ogs_nas_encode_payload_container_type(pkbuf, &pdu_session_establishment_request->payload_container_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_payload_container(pkbuf, &pdu_session_establishment_request->payload_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_session_status(pkbuf, &pdu_session_establishment_request->pdu_session_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_PRESENT) { + pdu_session_establishment_request->release_assistance_indication.type = (OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_release_assistance_indication(pkbuf, &pdu_session_establishment_request->release_assistance_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_uplink_data_status(pkbuf, &pdu_session_establishment_request->uplink_data_status); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_message_container(pkbuf, &pdu_session_establishment_request->nas_message_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_establishment_request->presencemask & OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_additional_information(pkbuf, &pdu_session_establishment_request->additional_information); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_establishment_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_establishment_accept_t *pdu_session_establishment_accept = &message->gsm.pdu_session_establishment_accept; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_ESTABLISHMENT_ACCEPT"); + + size = ogs_nas_encode_s_nssai(pkbuf, &pdu_session_establishment_accept->s_nssai); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_establishment_accept->eap_message); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_pdu_session_establishment_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_establishment_reject_t *pdu_session_establishment_reject = &message->gsm.pdu_session_establishment_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_ESTABLISHMENT_REJECT"); + + size = ogs_nas_encode_s_nssai(pkbuf, &pdu_session_establishment_reject->s_nssai); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_establishment_reject->eap_message); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_pdu_session_authentication_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_authentication_command_t *pdu_session_authentication_command = &message->gsm.pdu_session_authentication_command; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_AUTHENTICATION_COMMAND"); + + size = ogs_nas_encode_s_nssai(pkbuf, &pdu_session_authentication_command->s_nssai); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_authentication_command->eap_message); + ogs_assert(size >= 0); + encoded += size; + + return encoded; +} + +int ogs_nas_encode_pdu_session_authentication_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_authentication_complete_t *pdu_session_authentication_complete = &message->gsm.pdu_session_authentication_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_AUTHENTICATION_COMPLETE"); + + size = ogs_nas_encode_integrity_protection_maximum_data_rate(pkbuf, &pdu_session_authentication_complete->integrity_protection_maximum_data_rate); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_PRESENT) { + pdu_session_authentication_complete->pdu_session_type.type = (OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_TYPE >> 4); + + size = ogs_nas_encode_pdu_session_type(pkbuf, &pdu_session_authentication_complete->pdu_session_type); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_PRESENT) { + pdu_session_authentication_complete->ssc_mode.type = (OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_TYPE >> 4); + + size = ogs_nas_encode_ssc_mode(pkbuf, &pdu_session_authentication_complete->ssc_mode); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_capability(pkbuf, &pdu_session_authentication_complete->gsm_capability); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_maximum_number_of_supported_packet_filters(pkbuf, &pdu_session_authentication_complete->maximum_number_of_supported_packet_filters); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT) { + pdu_session_authentication_complete->always_on_pdu_session_requested.type = (OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE >> 4); + + size = ogs_nas_encode_always_on_pdu_session_requested(pkbuf, &pdu_session_authentication_complete->always_on_pdu_session_requested); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_sm_pdu_dn_request_container(pkbuf, &pdu_session_authentication_complete->sm_pdu_dn_request_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_authentication_complete->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_header_compression_configuration(pkbuf, &pdu_session_authentication_complete->header_compression_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ds_tt_ethernet_port_mac_address(pkbuf, &pdu_session_authentication_complete->ds_tt_ethernet_port_mac_address); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_ue_ds_tt_residence_time(pkbuf, &pdu_session_authentication_complete->ue_ds_tt_residence_time); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_complete->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_port_management_information_container(pkbuf, &pdu_session_authentication_complete->port_management_information_container); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_authentication_result(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_authentication_result_t *pdu_session_authentication_result = &message->gsm.pdu_session_authentication_result; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_AUTHENTICATION_RESULT"); + + size = ogs_nas_encode_pdu_session_type(pkbuf, &pdu_session_authentication_result->selected_pdu_session_type); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_rules(pkbuf, &pdu_session_authentication_result->authorized_qos_rules); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_session_ambr(pkbuf, &pdu_session_authentication_result->session_ambr); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_authentication_result->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_pdu_address(pkbuf, &pdu_session_authentication_result->pdu_address); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer(pkbuf, &pdu_session_authentication_result->rq_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_s_nssai(pkbuf, &pdu_session_authentication_result->s_nssai); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT) { + pdu_session_authentication_result->always_on_pdu_session_indication.type = (OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_always_on_pdu_session_indication(pkbuf, &pdu_session_authentication_result->always_on_pdu_session_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_mapped_eps_bearer_contexts(pkbuf, &pdu_session_authentication_result->mapped_eps_bearer_contexts); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_authentication_result->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_flow_descriptions(pkbuf, &pdu_session_authentication_result->authorized_qos_flow_descriptions); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_authentication_result->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_dnn(pkbuf, &pdu_session_authentication_result->dnn); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_network_feature_support(pkbuf, &pdu_session_authentication_result->gsm_network_feature_support); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_serving_plmn_rate_control(pkbuf, &pdu_session_authentication_result->serving_plmn_rate_control); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_atsss_container(pkbuf, &pdu_session_authentication_result->atsss_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_PRESENT) { + pdu_session_authentication_result->control_plane_only_indication.type = (OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_control_plane_only_indication(pkbuf, &pdu_session_authentication_result->control_plane_only_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_authentication_result->presencemask & OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_header_compression_configuration(pkbuf, &pdu_session_authentication_result->header_compression_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_modification_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_modification_request_t *pdu_session_modification_request = &message->gsm.pdu_session_modification_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_MODIFICATION_REQUEST"); + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_modification_request->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &pdu_session_modification_request->back_off_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_PRESENT) { + pdu_session_modification_request->allowed_ssc_mode.type = (OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_TYPE >> 4); + + size = ogs_nas_encode_allowed_ssc_mode(pkbuf, &pdu_session_modification_request->allowed_ssc_mode); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_modification_request->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_modification_request->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_re_attempt_indicator(pkbuf, &pdu_session_modification_request->re_attempt_indicator); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_request->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_congestion_re_attempt_indicator(pkbuf, &pdu_session_modification_request->gsm_congestion_re_attempt_indicator); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_modification_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_modification_reject_t *pdu_session_modification_reject = &message->gsm.pdu_session_modification_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_MODIFICATION_REJECT"); + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_modification_reject->eap_message); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_modification_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_modification_reject->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_modification_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_modification_command_t *pdu_session_modification_command = &message->gsm.pdu_session_modification_command; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_MODIFICATION_COMMAND"); + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_modification_command->eap_message); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_modification_command->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_modification_command->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_modification_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_modification_complete_t *pdu_session_modification_complete = &message->gsm.pdu_session_modification_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_MODIFICATION_COMPLETE"); + + if (pdu_session_modification_complete->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_eap_message(pkbuf, &pdu_session_modification_complete->eap_message); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_complete->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_modification_complete->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_modification_command_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_modification_command_reject_t *pdu_session_modification_command_reject = &message->gsm.pdu_session_modification_command_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_MODIFICATION_COMMAND_REJECT"); + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_capability(pkbuf, &pdu_session_modification_command_reject->gsm_capability); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_modification_command_reject->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_maximum_number_of_supported_packet_filters(pkbuf, &pdu_session_modification_command_reject->maximum_number_of_supported_packet_filters); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT) { + pdu_session_modification_command_reject->always_on_pdu_session_requested.type = (OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE >> 4); + + size = ogs_nas_encode_always_on_pdu_session_requested(pkbuf, &pdu_session_modification_command_reject->always_on_pdu_session_requested); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_integrity_protection_maximum_data_rate(pkbuf, &pdu_session_modification_command_reject->integrity_protection_maximum_data_rate); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_rules(pkbuf, &pdu_session_modification_command_reject->requested_qos_rules); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_flow_descriptions(pkbuf, &pdu_session_modification_command_reject->requested_qos_flow_descriptions); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_mapped_eps_bearer_contexts(pkbuf, &pdu_session_modification_command_reject->mapped_eps_bearer_contexts); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_modification_command_reject->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_port_management_information_container(pkbuf, &pdu_session_modification_command_reject->port_management_information_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_modification_command_reject->presencemask & OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_header_compression_configuration(pkbuf, &pdu_session_modification_command_reject->header_compression_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_release_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_release_request_t *pdu_session_release_request = &message->gsm.pdu_session_release_request; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_RELEASE_REQUEST"); + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_release_request->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_release_request->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer_3(pkbuf, &pdu_session_release_request->back_off_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_request->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_release_request->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_request->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_re_attempt_indicator(pkbuf, &pdu_session_release_request->re_attempt_indicator); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_request->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_congestion_re_attempt_indicator(pkbuf, &pdu_session_release_request->gsm_congestion_re_attempt_indicator); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_release_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_release_reject_t *pdu_session_release_reject = &message->gsm.pdu_session_release_reject; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_RELEASE_REJECT"); + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_release_reject->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_session_ambr(pkbuf, &pdu_session_release_reject->session_ambr); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_gprs_timer(pkbuf, &pdu_session_release_reject->rq_timer_value); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT) { + pdu_session_release_reject->always_on_pdu_session_indication.type = (OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE >> 4); + + size = ogs_nas_encode_always_on_pdu_session_indication(pkbuf, &pdu_session_release_reject->always_on_pdu_session_indication); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_rules(pkbuf, &pdu_session_release_reject->authorized_qos_rules); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_mapped_eps_bearer_contexts(pkbuf, &pdu_session_release_reject->mapped_eps_bearer_contexts); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_qos_flow_descriptions(pkbuf, &pdu_session_release_reject->authorized_qos_flow_descriptions); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_release_reject->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_atsss_container(pkbuf, &pdu_session_release_reject->atsss_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_header_compression_configuration(pkbuf, &pdu_session_release_reject->header_compression_configuration); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_port_management_information_container(pkbuf, &pdu_session_release_reject->port_management_information_container); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_reject->presencemask & OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_serving_plmn_rate_control(pkbuf, &pdu_session_release_reject->serving_plmn_rate_control); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_release_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_release_command_t *pdu_session_release_command = &message->gsm.pdu_session_release_command; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_RELEASE_COMMAND"); + + if (pdu_session_release_command->presencemask & OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_release_command->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + if (pdu_session_release_command->presencemask & OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_port_management_information_container(pkbuf, &pdu_session_release_command->port_management_information_container); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_pdu_session_release_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_pdu_session_release_complete_t *pdu_session_release_complete = &message->gsm.pdu_session_release_complete; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode PDU_SESSION_RELEASE_COMPLETE"); + + size = ogs_nas_encode_5gsm_cause(pkbuf, &pdu_session_release_complete->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + + if (pdu_session_release_complete->presencemask & OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &pdu_session_release_complete->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +int ogs_nas_encode_5gsm_status(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) +{ + ogs_nas_5gsm_status_t *gsm_status = &message->gsm.gsm_status; + int encoded = 0; + int size = 0; + + ogs_trace("[NAS] Encode 5GSM_STATUS"); + + if (gsm_status->presencemask & OGS_NAS_5GSM_STATUS_5GSM_CAUSE_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_5GSM_STATUS_5GSM_CAUSE_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_5gsm_cause(pkbuf, &gsm_status->gsm_cause); + ogs_assert(size >= 0); + encoded += size; + } + + if (gsm_status->presencemask & OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { + size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); + ogs_assert(size >= 0); + encoded += size; + + size = ogs_nas_encode_extended_protocol_configuration_options(pkbuf, &gsm_status->extended_protocol_configuration_options); + ogs_assert(size >= 0); + encoded += size; + } + + return encoded; +} + +ogs_pkbuf_t *ogs_nas_5gmm_encode(ogs_nas_message_t *message) +{ + ogs_pkbuf_t *pkbuf = NULL; + int size = 0; + int encoded = 0; + + ogs_assert(message); + + /* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ + pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); + ogs_assert(pkbuf); + ogs_pkbuf_reserve(pkbuf, OGS_NAS_HEADROOM); + ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-OGS_NAS_HEADROOM); + + size = sizeof(ogs_nas_5gmm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + + memcpy(pkbuf->data - size, &message->gmm.h, size); + encoded += size; + + switch(message->gmm.h.message_type) { + case OGS_NAS_REGISTRATION_REQUEST: + size = ogs_nas_encode_registration_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_REGISTRATION_ACCEPT: + size = ogs_nas_encode_registration_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_REGISTRATION_COMPLETE: + size = ogs_nas_encode_registration_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_REGISTRATION_REJECT: + size = ogs_nas_encode_registration_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DEREGISTRATION_REQUEST: + size = ogs_nas_encode_deregistration_request_to_ue(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DEREGISTRATION_ACCEPT: + break; + case OGS_NAS_SERVICE_REQUEST: + size = ogs_nas_encode_service_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SERVICE_REJECT: + size = ogs_nas_encode_service_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SERVICE_ACCEPT: + size = ogs_nas_encode_service_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMMAND: + size = ogs_nas_encode_configuration_update_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_CONFIGURATION_UPDATE_COMPLETE: + size = ogs_nas_encode_configuration_update_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_REQUEST: + size = ogs_nas_encode_authentication_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESPONSE: + size = ogs_nas_encode_authentication_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_REJECT: + size = ogs_nas_encode_authentication_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_FAILURE: + size = ogs_nas_encode_authentication_failure(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESULT: + size = ogs_nas_encode_authentication_result(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_IDENTITY_REQUEST: + size = ogs_nas_encode_identity_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_IDENTITY_RESPONSE: + size = ogs_nas_encode_identity_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND: + size = ogs_nas_encode_security_mode_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE: + size = ogs_nas_encode_security_mode_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_REJECT: + size = ogs_nas_encode_security_mode_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_5GMM_STATUS: + size = ogs_nas_encode_5gmm_status(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_NOTIFICATION: + size = ogs_nas_encode_notification(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_NOTIFICATION_RESPONSE: + size = ogs_nas_encode_notification_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_UL_NAS_TRANSPORT: + size = ogs_nas_encode_ul_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DL_NAS_TRANSPORT: + size = ogs_nas_encode_dl_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gmm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); + + pkbuf->len = encoded; + + return pkbuf; +} + +ogs_pkbuf_t *ogs_nas_5gsm_encode(ogs_nas_message_t *message) +{ + ogs_pkbuf_t *pkbuf = NULL; + int size = 0; + int encoded = 0; + + ogs_assert(message); + + /* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ + pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); + ogs_assert(pkbuf); + ogs_pkbuf_reserve(pkbuf, OGS_NAS_HEADROOM); + ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-OGS_NAS_HEADROOM); + + size = sizeof(ogs_nas_5gsm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &message->gsm.h, size); + encoded += size; + + switch(message->gsm.h.message_type) { + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST: + size = ogs_nas_encode_pdu_session_establishment_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_ACCEPT: + size = ogs_nas_encode_pdu_session_establishment_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_ESTABLISHMENT_REJECT: + size = ogs_nas_encode_pdu_session_establishment_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMMAND: + size = ogs_nas_encode_pdu_session_authentication_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE: + size = ogs_nas_encode_pdu_session_authentication_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT: + size = ogs_nas_encode_pdu_session_authentication_result(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST: + size = ogs_nas_encode_pdu_session_modification_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_REJECT: + size = ogs_nas_encode_pdu_session_modification_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND: + size = ogs_nas_encode_pdu_session_modification_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE: + size = ogs_nas_encode_pdu_session_modification_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT: + size = ogs_nas_encode_pdu_session_modification_command_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REQUEST: + size = ogs_nas_encode_pdu_session_release_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_REJECT: + size = ogs_nas_encode_pdu_session_release_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_COMMAND: + size = ogs_nas_encode_pdu_session_release_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDU_SESSION_RELEASE_COMPLETE: + size = ogs_nas_encode_pdu_session_release_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_5GSM_STATUS: + size = ogs_nas_encode_5gsm_status(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gsm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); + pkbuf->len = encoded; + + return pkbuf; +} + +ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message) +{ + ogs_assert(message); + + ogs_assert(message->gmm.h.extended_protocol_discriminator == + message->gsm.h.extended_protocol_discriminator); + + if (message->gmm.h.extended_protocol_discriminator == + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_EMM) + return ogs_nas_5gmm_encode(message); + else if (message->gmm.h.extended_protocol_discriminator == + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_ESM) + return ogs_nas_5gsm_encode(message); + + return NULL; +} diff --git a/lib/nas/5gs/ies.c b/lib/nas/5gs/ies.c new file mode 100644 index 000000000..c27084998 --- /dev/null +++ b/lib/nas/5gs/ies.c @@ -0,0 +1,3678 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 21:20:09.023713 by acetcom + * from 24501-g41.docx + ******************************************************************************/ + +#include "ogs-nas-5gs.h" + +int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) +{ + uint16_t size = sizeof(uint8_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &type, size); + + return size; +} +/* 9.11.2.1 Additional information + * O TLV 3-n */ +int ogs_nas_decode_additional_information(ogs_nas_additional_information_t *additional_information, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_additional_information_t *source = (ogs_nas_additional_information_t *)pkbuf->data; + + additional_information->length = source->length; + size = additional_information->length + sizeof(additional_information->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(additional_information, pkbuf->data - size, size); + + ogs_trace(" ADDITIONAL_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_additional_information(ogs_pkbuf_t *pkbuf, ogs_nas_additional_information_t *additional_information) +{ + uint16_t size = additional_information->length + sizeof(additional_information->length); + ogs_nas_additional_information_t target; + + memcpy(&target, additional_information, sizeof(ogs_nas_additional_information_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ADDITIONAL_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.1A Access type + * M V 1/2 */ +int ogs_nas_decode_access_type(ogs_nas_access_type_t *access_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_access_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(access_type, pkbuf->data - size, size); + + ogs_trace(" ACCESS_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_access_type(ogs_pkbuf_t *pkbuf, ogs_nas_access_type_t *access_type) +{ + uint16_t size = sizeof(ogs_nas_access_type_t); + ogs_nas_access_type_t target; + + memcpy(&target, access_type, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ACCESS_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.1B DNN + * O TLV 3-102 */ +int ogs_nas_decode_dnn(ogs_nas_dnn_t *dnn, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_dnn_t *source = (ogs_nas_dnn_t *)pkbuf->data; + + dnn->length = source->length; + size = dnn->length + sizeof(dnn->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(dnn, pkbuf->data - size, size); + + { + char data_network_name[OGS_MAX_DNN_LEN]; + dnn->length = ogs_fqdn_parse(data_network_name, dnn->value, dnn->length); + ogs_cpystrn(dnn->value, data_network_name, ogs_min(dnn->length, OGS_MAX_DNN_LEN) + 1); + } + + ogs_trace(" DNN - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_dnn(ogs_pkbuf_t *pkbuf, ogs_nas_dnn_t *dnn) +{ + uint16_t size = dnn->length + sizeof(dnn->length); + ogs_nas_dnn_t target; + + memcpy(&target, dnn, sizeof(ogs_nas_dnn_t)); + target.length = ogs_fqdn_build(target.value, dnn->value, dnn->length); + size = target.length + sizeof(target.length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" DNN - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.2 EAP message + * O TLV-E 7-1503 */ +int ogs_nas_decode_eap_message(ogs_nas_eap_message_t *eap_message, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_eap_message_t *source = (ogs_nas_eap_message_t *)pkbuf->data; + + eap_message->length = be16toh(source->length); + size = eap_message->length + sizeof(eap_message->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + eap_message->buffer = pkbuf->data - size + sizeof(eap_message->length); + + ogs_trace(" EAP_MESSAGE - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)eap_message->buffer, eap_message->length); + + return size; +} + +int ogs_nas_encode_eap_message(ogs_pkbuf_t *pkbuf, ogs_nas_eap_message_t *eap_message) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(eap_message); + ogs_assert(eap_message->buffer); + + size = sizeof(eap_message->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(eap_message->length); + memcpy(pkbuf->data - size, &target, size); + + size = eap_message->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, eap_message->buffer, size); + + ogs_trace(" EAP_MESSAGE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return eap_message->length + sizeof(eap_message->length); +} + +/* 9.11.2.3 GPRS timer + * O TV 2 */ +int ogs_nas_decode_gprs_timer(ogs_nas_gprs_timer_t *gprs_timer, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_gprs_timer_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gprs_timer, pkbuf->data - size, size); + + ogs_trace(" GPRS_TIMER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_gprs_timer(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_t *gprs_timer) +{ + uint16_t size = sizeof(ogs_nas_gprs_timer_t); + ogs_nas_gprs_timer_t target; + + memcpy(&target, gprs_timer, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" GPRS_TIMER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.4 GPRS timer 2 + * O TLV 3 */ +int ogs_nas_decode_gprs_timer_2(ogs_nas_gprs_timer_2_t *gprs_timer_2, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_gprs_timer_2_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gprs_timer_2, pkbuf->data - size, size); + + ogs_trace(" GPRS_TIMER_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_gprs_timer_2(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_2_t *gprs_timer_2) +{ + uint16_t size = gprs_timer_2->length + sizeof(gprs_timer_2->length); + ogs_nas_gprs_timer_2_t target; + + memcpy(&target, gprs_timer_2, sizeof(ogs_nas_gprs_timer_2_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" GPRS_TIMER_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.5 GPRS timer 3 + * O TLV 3 */ +int ogs_nas_decode_gprs_timer_3(ogs_nas_gprs_timer_3_t *gprs_timer_3, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_gprs_timer_3_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gprs_timer_3, pkbuf->data - size, size); + + ogs_trace(" GPRS_TIMER_3 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_gprs_timer_3(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_3_t *gprs_timer_3) +{ + uint16_t size = gprs_timer_3->length + sizeof(gprs_timer_3->length); + ogs_nas_gprs_timer_3_t target; + + memcpy(&target, gprs_timer_3, sizeof(ogs_nas_gprs_timer_3_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" GPRS_TIMER_3 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.2.8 S-NSSAI + * O TLV 3-10 */ +int ogs_nas_decode_s_nssai(ogs_nas_s_nssai_t *s_nssai, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_s_nssai_t *source = (ogs_nas_s_nssai_t *)pkbuf->data; + + s_nssai->length = source->length; + size = s_nssai->length + sizeof(s_nssai->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(s_nssai, pkbuf->data - size, size); + + ogs_trace(" S_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_s_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_s_nssai_t *s_nssai) +{ + uint16_t size = s_nssai->length + sizeof(s_nssai->length); + ogs_nas_s_nssai_t target; + + memcpy(&target, s_nssai, sizeof(ogs_nas_s_nssai_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" S_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.1 5GMM capability + * O TLV 3-15 */ +int ogs_nas_decode_5gmm_capability(ogs_nas_5gmm_capability_t *gmm_capability, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gmm_capability_t *source = (ogs_nas_5gmm_capability_t *)pkbuf->data; + + gmm_capability->length = source->length; + size = gmm_capability->length + sizeof(gmm_capability->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gmm_capability, pkbuf->data - size, size); + + ogs_trace(" 5GMM_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gmm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gmm_capability_t *gmm_capability) +{ + uint16_t size = gmm_capability->length + sizeof(gmm_capability->length); + ogs_nas_5gmm_capability_t target; + + memcpy(&target, gmm_capability, sizeof(ogs_nas_5gmm_capability_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GMM_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.10 ABBA + * M LV 3-n */ +int ogs_nas_decode_abba(ogs_nas_abba_t *abba, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_abba_t *source = (ogs_nas_abba_t *)pkbuf->data; + + abba->length = source->length; + size = abba->length + sizeof(abba->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(abba, pkbuf->data - size, size); + + ogs_trace(" ABBA - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_abba(ogs_pkbuf_t *pkbuf, ogs_nas_abba_t *abba) +{ + uint16_t size = abba->length + sizeof(abba->length); + ogs_nas_abba_t target; + + memcpy(&target, abba, sizeof(ogs_nas_abba_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ABBA - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.12 Additional 5G security information + * O TLV 3 */ +int ogs_nas_decode_additional_5g_security_information(ogs_nas_additional_5g_security_information_t *additional_security_information, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_additional_5g_security_information_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(additional_security_information, pkbuf->data - size, size); + + ogs_trace(" ADDITIONAL_5G_SECURITY_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_additional_5g_security_information(ogs_pkbuf_t *pkbuf, ogs_nas_additional_5g_security_information_t *additional_security_information) +{ + uint16_t size = additional_security_information->length + sizeof(additional_security_information->length); + ogs_nas_additional_5g_security_information_t target; + + memcpy(&target, additional_security_information, sizeof(ogs_nas_additional_5g_security_information_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ADDITIONAL_5G_SECURITY_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.12A Additional information requested + * O TLV 3 */ +int ogs_nas_decode_additional_information_requested(ogs_nas_additional_information_requested_t *additional_information_requested, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_additional_information_requested_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(additional_information_requested, pkbuf->data - size, size); + + ogs_trace(" ADDITIONAL_INFORMATION_REQUESTED - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_additional_information_requested(ogs_pkbuf_t *pkbuf, ogs_nas_additional_information_requested_t *additional_information_requested) +{ + uint16_t size = additional_information_requested->length + sizeof(additional_information_requested->length); + ogs_nas_additional_information_requested_t target; + + memcpy(&target, additional_information_requested, sizeof(ogs_nas_additional_information_requested_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ADDITIONAL_INFORMATION_REQUESTED - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.13 Allowed PDU session status + * O TLV 4-34 */ +int ogs_nas_decode_allowed_pdu_session_status(ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_allowed_pdu_session_status_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(allowed_pdu_session_status, pkbuf->data - size, size); + + ogs_trace(" ALLOWED_PDU_SESSION_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_allowed_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status) +{ + uint16_t size = allowed_pdu_session_status->length + sizeof(allowed_pdu_session_status->length); + ogs_nas_allowed_pdu_session_status_t target; + + memcpy(&target, allowed_pdu_session_status, sizeof(ogs_nas_allowed_pdu_session_status_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" ALLOWED_PDU_SESSION_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.14 Authentication failure parameter + * O TLV 16 */ +int ogs_nas_decode_authentication_failure_parameter(ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_authentication_failure_parameter_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(authentication_failure_parameter, pkbuf->data - size, size); + + ogs_trace(" AUTHENTICATION_FAILURE_PARAMETER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_authentication_failure_parameter(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter) +{ + uint16_t size = authentication_failure_parameter->length + sizeof(authentication_failure_parameter->length); + ogs_nas_authentication_failure_parameter_t target; + + memcpy(&target, authentication_failure_parameter, sizeof(ogs_nas_authentication_failure_parameter_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" AUTHENTICATION_FAILURE_PARAMETER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.15 Authentication parameter AUTN + * O TLV 18 */ +int ogs_nas_decode_authentication_parameter_autn(ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_authentication_parameter_autn_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(authentication_parameter_autn, pkbuf->data - size, size); + + ogs_trace(" AUTHENTICATION_PARAMETER_AUTN - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_authentication_parameter_autn(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn) +{ + uint16_t size = authentication_parameter_autn->length + sizeof(authentication_parameter_autn->length); + ogs_nas_authentication_parameter_autn_t target; + + memcpy(&target, authentication_parameter_autn, sizeof(ogs_nas_authentication_parameter_autn_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" AUTHENTICATION_PARAMETER_AUTN - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.16 Authentication parameter RAND + * O TV 17 */ +int ogs_nas_decode_authentication_parameter_rand(ogs_nas_authentication_parameter_rand_t *authentication_parameter_rand, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_authentication_parameter_rand_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(authentication_parameter_rand, pkbuf->data - size, size); + + ogs_trace(" AUTHENTICATION_PARAMETER_RAND - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_authentication_parameter_rand(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_parameter_rand_t *authentication_parameter_rand) +{ + uint16_t size = sizeof(ogs_nas_authentication_parameter_rand_t); + ogs_nas_authentication_parameter_rand_t target; + + memcpy(&target, authentication_parameter_rand, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" AUTHENTICATION_PARAMETER_RAND - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.17 Authentication response parameter + * O TLV 18 */ +int ogs_nas_decode_authentication_response_parameter(ogs_nas_authentication_response_parameter_t *authentication_response_parameter, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_authentication_response_parameter_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(authentication_response_parameter, pkbuf->data - size, size); + + ogs_trace(" AUTHENTICATION_RESPONSE_PARAMETER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_authentication_response_parameter(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_response_parameter_t *authentication_response_parameter) +{ + uint16_t size = authentication_response_parameter->length + sizeof(authentication_response_parameter->length); + ogs_nas_authentication_response_parameter_t target; + + memcpy(&target, authentication_response_parameter, sizeof(ogs_nas_authentication_response_parameter_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" AUTHENTICATION_RESPONSE_PARAMETER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.18 Configuration update indication + * O TV 1 */ +int ogs_nas_decode_configuration_update_indication(ogs_nas_configuration_update_indication_t *configuration_update_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(configuration_update_indication, pkbuf->data - 1, 1); + + ogs_trace(" CONFIGURATION_UPDATE_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_configuration_update_indication(ogs_pkbuf_t *pkbuf, ogs_nas_configuration_update_indication_t *configuration_update_indication) +{ + uint16_t size = sizeof(ogs_nas_configuration_update_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, configuration_update_indication, size); + + ogs_trace(" CONFIGURATION_UPDATE_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.18A CAG information list + * O TLV-E 3-n */ +int ogs_nas_decode_cag_information_list(ogs_nas_cag_information_list_t *cag_information_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_cag_information_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + cag_information_list->buffer = pkbuf->data - size + sizeof(cag_information_list->length); + + ogs_trace(" CAG_INFORMATION_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)cag_information_list->buffer, cag_information_list->length); + + return size; +} + +int ogs_nas_encode_cag_information_list(ogs_pkbuf_t *pkbuf, ogs_nas_cag_information_list_t *cag_information_list) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(cag_information_list); + ogs_assert(cag_information_list->buffer); + + size = sizeof(cag_information_list->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(cag_information_list->length); + memcpy(pkbuf->data - size, &target, size); + + size = cag_information_list->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, cag_information_list->buffer, size); + + ogs_trace(" CAG_INFORMATION_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return cag_information_list->length + sizeof(cag_information_list->length); +} + +/* 9.11.3.18B CIoT small data container + * O TLV 4-257 */ +int ogs_nas_decode_ciot_small_data_container(ogs_nas_ciot_small_data_container_t *ciot_small_data_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ciot_small_data_container_t *source = (ogs_nas_ciot_small_data_container_t *)pkbuf->data; + + ciot_small_data_container->length = source->length; + size = ciot_small_data_container->length + sizeof(ciot_small_data_container->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ciot_small_data_container, pkbuf->data - size, size); + + ogs_trace(" CIOT_SMALL_DATA_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ciot_small_data_container(ogs_pkbuf_t *pkbuf, ogs_nas_ciot_small_data_container_t *ciot_small_data_container) +{ + uint16_t size = ciot_small_data_container->length + sizeof(ciot_small_data_container->length); + ogs_nas_ciot_small_data_container_t target; + + memcpy(&target, ciot_small_data_container, sizeof(ogs_nas_ciot_small_data_container_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" CIOT_SMALL_DATA_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.18C Ciphering key data + * O TLV-E x-n */ +int ogs_nas_decode_ciphering_key_data(ogs_nas_ciphering_key_data_t *ciphering_key_data, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ciphering_key_data_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + ciphering_key_data->buffer = pkbuf->data - size + sizeof(ciphering_key_data->length); + + ogs_trace(" CIPHERING_KEY_DATA - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)ciphering_key_data->buffer, ciphering_key_data->length); + + return size; +} + +int ogs_nas_encode_ciphering_key_data(ogs_pkbuf_t *pkbuf, ogs_nas_ciphering_key_data_t *ciphering_key_data) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(ciphering_key_data); + ogs_assert(ciphering_key_data->buffer); + + size = sizeof(ciphering_key_data->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(ciphering_key_data->length); + memcpy(pkbuf->data - size, &target, size); + + size = ciphering_key_data->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ciphering_key_data->buffer, size); + + ogs_trace(" CIPHERING_KEY_DATA - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return ciphering_key_data->length + sizeof(ciphering_key_data->length); +} + +/* 9.11.3.18D Control plane service type + * M V 1/2 */ +int ogs_nas_decode_control_plane_service_type(ogs_nas_control_plane_service_type_t *control_plane_service_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_control_plane_service_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(control_plane_service_type, pkbuf->data - size, size); + + ogs_trace(" CONTROL_PLANE_SERVICE_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_control_plane_service_type(ogs_pkbuf_t *pkbuf, ogs_nas_control_plane_service_type_t *control_plane_service_type) +{ + uint16_t size = sizeof(ogs_nas_control_plane_service_type_t); + ogs_nas_control_plane_service_type_t target; + + memcpy(&target, control_plane_service_type, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" CONTROL_PLANE_SERVICE_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.19 Daylight saving time + * O TLV 3 */ +int ogs_nas_decode_daylight_saving_time(ogs_nas_daylight_saving_time_t *daylight_saving_time, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_daylight_saving_time_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(daylight_saving_time, pkbuf->data - size, size); + + ogs_trace(" DAYLIGHT_SAVING_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_daylight_saving_time(ogs_pkbuf_t *pkbuf, ogs_nas_daylight_saving_time_t *daylight_saving_time) +{ + uint16_t size = daylight_saving_time->length + sizeof(daylight_saving_time->length); + ogs_nas_daylight_saving_time_t target; + + memcpy(&target, daylight_saving_time, sizeof(ogs_nas_daylight_saving_time_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" DAYLIGHT_SAVING_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.2 5GMM cause + * M V 1 */ +int ogs_nas_decode_5gmm_cause(ogs_nas_5gmm_cause_t *gmm_cause, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_5gmm_cause_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gmm_cause, pkbuf->data - size, size); + + ogs_trace(" 5GMM_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gmm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_5gmm_cause_t *gmm_cause) +{ + uint16_t size = sizeof(ogs_nas_5gmm_cause_t); + ogs_nas_5gmm_cause_t target; + + memcpy(&target, gmm_cause, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GMM_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.20 De-registration type + * M V 1/2 */ +int ogs_nas_decode_de_registration_type(ogs_nas_de_registration_type_t *de_registration_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_de_registration_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(de_registration_type, pkbuf->data - size, size); + + ogs_trace(" DE_REGISTRATION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_de_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_de_registration_type_t *de_registration_type) +{ + uint16_t size = sizeof(ogs_nas_de_registration_type_t); + ogs_nas_de_registration_type_t target; + + memcpy(&target, de_registration_type, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" DE_REGISTRATION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.23 Emergency number list + * O TLV 5-50 */ +int ogs_nas_decode_emergency_number_list(ogs_nas_emergency_number_list_t *emergency_number_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_emergency_number_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(emergency_number_list, pkbuf->data - size, size); + + ogs_trace(" EMERGENCY_NUMBER_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_emergency_number_list_t *emergency_number_list) +{ + uint16_t size = emergency_number_list->length + sizeof(emergency_number_list->length); + ogs_nas_emergency_number_list_t target; + + memcpy(&target, emergency_number_list, sizeof(ogs_nas_emergency_number_list_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" EMERGENCY_NUMBER_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.23A EPS bearer context status + * O TLV 4 */ +int ogs_nas_decode_eps_bearer_context_status(ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_eps_bearer_context_status_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(eps_bearer_context_status, pkbuf->data - size, size); + + ogs_trace(" EPS_BEARER_CONTEXT_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_eps_bearer_context_status(ogs_pkbuf_t *pkbuf, ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status) +{ + uint16_t size = eps_bearer_context_status->length + sizeof(eps_bearer_context_status->length); + ogs_nas_eps_bearer_context_status_t target; + + memcpy(&target, eps_bearer_context_status, sizeof(ogs_nas_eps_bearer_context_status_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" EPS_BEARER_CONTEXT_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.24 EPS NAS message container + * O TLV-E 4-n */ +int ogs_nas_decode_eps_nas_message_container(ogs_nas_eps_nas_message_container_t *eps_nas_message_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_eps_nas_message_container_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + eps_nas_message_container->buffer = pkbuf->data - size + sizeof(eps_nas_message_container->length); + + ogs_trace(" EPS_NAS_MESSAGE_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)eps_nas_message_container->buffer, eps_nas_message_container->length); + + return size; +} + +int ogs_nas_encode_eps_nas_message_container(ogs_pkbuf_t *pkbuf, ogs_nas_eps_nas_message_container_t *eps_nas_message_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(eps_nas_message_container); + ogs_assert(eps_nas_message_container->buffer); + + size = sizeof(eps_nas_message_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(eps_nas_message_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = eps_nas_message_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, eps_nas_message_container->buffer, size); + + ogs_trace(" EPS_NAS_MESSAGE_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return eps_nas_message_container->length + sizeof(eps_nas_message_container->length); +} + +/* 9.11.3.25 EPS NAS security algorithms + * O TV 2 */ +int ogs_nas_decode_eps_nas_security_algorithms(ogs_nas_eps_nas_security_algorithms_t *eps_nas_security_algorithms, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_eps_nas_security_algorithms_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(eps_nas_security_algorithms, pkbuf->data - size, size); + + ogs_trace(" EPS_NAS_SECURITY_ALGORITHMS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_eps_nas_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_eps_nas_security_algorithms_t *eps_nas_security_algorithms) +{ + uint16_t size = sizeof(ogs_nas_eps_nas_security_algorithms_t); + ogs_nas_eps_nas_security_algorithms_t target; + + memcpy(&target, eps_nas_security_algorithms, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" EPS_NAS_SECURITY_ALGORITHMS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.26 Extended emergency number list + * O TLV-E 7-65538 */ +int ogs_nas_decode_extended_emergency_number_list(ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_extended_emergency_number_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + extended_emergency_number_list->buffer = pkbuf->data - size + sizeof(extended_emergency_number_list->length); + + ogs_trace(" EXTENDED_EMERGENCY_NUMBER_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)extended_emergency_number_list->buffer, extended_emergency_number_list->length); + + return size; +} + +int ogs_nas_encode_extended_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(extended_emergency_number_list); + ogs_assert(extended_emergency_number_list->buffer); + + size = sizeof(extended_emergency_number_list->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(extended_emergency_number_list->length); + memcpy(pkbuf->data - size, &target, size); + + size = extended_emergency_number_list->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, extended_emergency_number_list->buffer, size); + + ogs_trace(" EXTENDED_EMERGENCY_NUMBER_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return extended_emergency_number_list->length + sizeof(extended_emergency_number_list->length); +} + +/* 9.11.3.26A Extended DRX parameters + * O TLV 3 */ +int ogs_nas_decode_extended_drx_parameters(ogs_nas_extended_drx_parameters_t *extended_drx_parameters, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_extended_drx_parameters_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(extended_drx_parameters, pkbuf->data - size, size); + + ogs_trace(" EXTENDED_DRX_PARAMETERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_extended_drx_parameters(ogs_pkbuf_t *pkbuf, ogs_nas_extended_drx_parameters_t *extended_drx_parameters) +{ + uint16_t size = extended_drx_parameters->length + sizeof(extended_drx_parameters->length); + ogs_nas_extended_drx_parameters_t target; + + memcpy(&target, extended_drx_parameters, sizeof(ogs_nas_extended_drx_parameters_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" EXTENDED_DRX_PARAMETERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.28 IMEISV request + * O TV 1 */ +int ogs_nas_decode_imeisv_request(ogs_nas_imeisv_request_t *imeisv_request, ogs_pkbuf_t *pkbuf) +{ + memcpy(imeisv_request, pkbuf->data - 1, 1); + + ogs_trace(" IMEISV_REQUEST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_imeisv_request(ogs_pkbuf_t *pkbuf, ogs_nas_imeisv_request_t *imeisv_request) +{ + uint16_t size = sizeof(ogs_nas_imeisv_request_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, imeisv_request, size); + + ogs_trace(" IMEISV_REQUEST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.29 LADN indication + * O TLV-E 3-811 */ +int ogs_nas_decode_ladn_indication(ogs_nas_ladn_indication_t *ladn_indication, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ladn_indication_t *source = (ogs_nas_ladn_indication_t *)pkbuf->data; + + ladn_indication->length = be16toh(source->length); + size = ladn_indication->length + sizeof(ladn_indication->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + ladn_indication->buffer = pkbuf->data - size + sizeof(ladn_indication->length); + + ogs_trace(" LADN_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)ladn_indication->buffer, ladn_indication->length); + + return size; +} + +int ogs_nas_encode_ladn_indication(ogs_pkbuf_t *pkbuf, ogs_nas_ladn_indication_t *ladn_indication) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(ladn_indication); + ogs_assert(ladn_indication->buffer); + + size = sizeof(ladn_indication->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(ladn_indication->length); + memcpy(pkbuf->data - size, &target, size); + + size = ladn_indication->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ladn_indication->buffer, size); + + ogs_trace(" LADN_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return ladn_indication->length + sizeof(ladn_indication->length); +} + +/* 9.11.3.2A 5GS DRX parameters + * O TLV 3 */ +int ogs_nas_decode_5gs_drx_parameters(ogs_nas_5gs_drx_parameters_t *drx_parameters, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_drx_parameters_t *source = (ogs_nas_5gs_drx_parameters_t *)pkbuf->data; + + drx_parameters->length = source->length; + size = drx_parameters->length + sizeof(drx_parameters->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(drx_parameters, pkbuf->data - size, size); + + ogs_trace(" 5GS_DRX_PARAMETERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_drx_parameters(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_drx_parameters_t *drx_parameters) +{ + uint16_t size = drx_parameters->length + sizeof(drx_parameters->length); + ogs_nas_5gs_drx_parameters_t target; + + memcpy(&target, drx_parameters, sizeof(ogs_nas_5gs_drx_parameters_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_DRX_PARAMETERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.3 5GS identity type + * M V 1/2 */ +int ogs_nas_decode_5gs_identity_type(ogs_nas_5gs_identity_type_t *identity_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_5gs_identity_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(identity_type, pkbuf->data - size, size); + + ogs_trace(" 5GS_IDENTITY_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_identity_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_identity_type_t *identity_type) +{ + uint16_t size = sizeof(ogs_nas_5gs_identity_type_t); + ogs_nas_5gs_identity_type_t target; + + memcpy(&target, identity_type, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_IDENTITY_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.30 LADN information + * O TLV-E 12-1715 */ +int ogs_nas_decode_ladn_information(ogs_nas_ladn_information_t *ladn_information, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ladn_information_t *source = (ogs_nas_ladn_information_t *)pkbuf->data; + + ladn_information->length = be16toh(source->length); + size = ladn_information->length + sizeof(ladn_information->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + ladn_information->buffer = pkbuf->data - size + sizeof(ladn_information->length); + + ogs_trace(" LADN_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)ladn_information->buffer, ladn_information->length); + + return size; +} + +int ogs_nas_encode_ladn_information(ogs_pkbuf_t *pkbuf, ogs_nas_ladn_information_t *ladn_information) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(ladn_information); + ogs_assert(ladn_information->buffer); + + size = sizeof(ladn_information->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(ladn_information->length); + memcpy(pkbuf->data - size, &target, size); + + size = ladn_information->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ladn_information->buffer, size); + + ogs_trace(" LADN_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return ladn_information->length + sizeof(ladn_information->length); +} + +/* 9.11.3.31 MICO indication + * O TV 1 */ +int ogs_nas_decode_mico_indication(ogs_nas_mico_indication_t *mico_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(mico_indication, pkbuf->data - 1, 1); + + ogs_trace(" MICO_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_mico_indication(ogs_pkbuf_t *pkbuf, ogs_nas_mico_indication_t *mico_indication) +{ + uint16_t size = sizeof(ogs_nas_mico_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, mico_indication, size); + + ogs_trace(" MICO_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.31A MA PDU session information + * O TV 1 */ +int ogs_nas_decode_ma_pdu_session_information(ogs_nas_ma_pdu_session_information_t *ma_pdu_session_information, ogs_pkbuf_t *pkbuf) +{ + memcpy(ma_pdu_session_information, pkbuf->data - 1, 1); + + ogs_trace(" MA_PDU_SESSION_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_ma_pdu_session_information(ogs_pkbuf_t *pkbuf, ogs_nas_ma_pdu_session_information_t *ma_pdu_session_information) +{ + uint16_t size = sizeof(ogs_nas_ma_pdu_session_information_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ma_pdu_session_information, size); + + ogs_trace(" MA_PDU_SESSION_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.31B Mapped NSSAI + * O TLV 3-42 */ +int ogs_nas_decode_mapped_nssai(ogs_nas_mapped_nssai_t *mapped_nssai, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_mapped_nssai_t *source = (ogs_nas_mapped_nssai_t *)pkbuf->data; + + mapped_nssai->length = source->length; + size = mapped_nssai->length + sizeof(mapped_nssai->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(mapped_nssai, pkbuf->data - size, size); + + ogs_trace(" MAPPED_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_mapped_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_mapped_nssai_t *mapped_nssai) +{ + uint16_t size = mapped_nssai->length + sizeof(mapped_nssai->length); + ogs_nas_mapped_nssai_t target; + + memcpy(&target, mapped_nssai, sizeof(ogs_nas_mapped_nssai_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" MAPPED_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.31C Mobile station classmark 2 + * O TLV 5 */ +int ogs_nas_decode_mobile_station_classmark_2(ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_mobile_station_classmark_2_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(mobile_station_classmark_2, pkbuf->data - size, size); + + ogs_trace(" MOBILE_STATION_CLASSMARK_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_mobile_station_classmark_2(ogs_pkbuf_t *pkbuf, ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2) +{ + uint16_t size = mobile_station_classmark_2->length + sizeof(mobile_station_classmark_2->length); + ogs_nas_mobile_station_classmark_2_t target; + + memcpy(&target, mobile_station_classmark_2, sizeof(ogs_nas_mobile_station_classmark_2_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" MOBILE_STATION_CLASSMARK_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.32 key set identifier + * O TV 1 */ +int ogs_nas_decode_key_set_identifier(ogs_nas_key_set_identifier_t *key_set_identifier, ogs_pkbuf_t *pkbuf) +{ + memcpy(key_set_identifier, pkbuf->data - 1, 1); + + ogs_trace(" KEY_SET_IDENTIFIER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_key_set_identifier(ogs_pkbuf_t *pkbuf, ogs_nas_key_set_identifier_t *key_set_identifier) +{ + uint16_t size = sizeof(ogs_nas_key_set_identifier_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, key_set_identifier, size); + + ogs_trace(" KEY_SET_IDENTIFIER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.33 message container + * O TLV-E 4-n */ +int ogs_nas_decode_message_container(ogs_nas_message_container_t *message_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_message_container_t *source = (ogs_nas_message_container_t *)pkbuf->data; + + message_container->length = be16toh(source->length); + size = message_container->length + sizeof(message_container->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + message_container->buffer = pkbuf->data - size + sizeof(message_container->length); + + ogs_trace(" MESSAGE_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)message_container->buffer, message_container->length); + + return size; +} + +int ogs_nas_encode_message_container(ogs_pkbuf_t *pkbuf, ogs_nas_message_container_t *message_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(message_container); + ogs_assert(message_container->buffer); + + size = sizeof(message_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(message_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = message_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, message_container->buffer, size); + + ogs_trace(" MESSAGE_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return message_container->length + sizeof(message_container->length); +} + +/* 9.11.3.34 security algorithms + * M V 1 */ +int ogs_nas_decode_security_algorithms(ogs_nas_security_algorithms_t *security_algorithms, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_security_algorithms_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(security_algorithms, pkbuf->data - size, size); + + ogs_trace(" SECURITY_ALGORITHMS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_security_algorithms_t *security_algorithms) +{ + uint16_t size = sizeof(ogs_nas_security_algorithms_t); + ogs_nas_security_algorithms_t target; + + memcpy(&target, security_algorithms, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SECURITY_ALGORITHMS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.35 Network name + * O TLV 3-n */ +int ogs_nas_decode_network_name(ogs_nas_network_name_t *network_name, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_network_name_t *source = (ogs_nas_network_name_t *)pkbuf->data; + + network_name->length = source->length; + size = network_name->length + sizeof(network_name->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(network_name, pkbuf->data - size, size); + + ogs_trace(" NETWORK_NAME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_network_name(ogs_pkbuf_t *pkbuf, ogs_nas_network_name_t *network_name) +{ + uint16_t size = network_name->length + sizeof(network_name->length); + ogs_nas_network_name_t target; + + memcpy(&target, network_name, sizeof(ogs_nas_network_name_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" NETWORK_NAME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.36 Network slicing indication + * O TV 1 */ +int ogs_nas_decode_network_slicing_indication(ogs_nas_network_slicing_indication_t *network_slicing_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(network_slicing_indication, pkbuf->data - 1, 1); + + ogs_trace(" NETWORK_SLICING_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_network_slicing_indication(ogs_pkbuf_t *pkbuf, ogs_nas_network_slicing_indication_t *network_slicing_indication) +{ + uint16_t size = sizeof(ogs_nas_network_slicing_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, network_slicing_indication, size); + + ogs_trace(" NETWORK_SLICING_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.36A Non-3GPP NW provided policies + * O TV 1 */ +int ogs_nas_decode_non_3gpp_nw_provided_policies(ogs_nas_non_3gpp_nw_provided_policies_t *non_3gpp_nw_provided_policies, ogs_pkbuf_t *pkbuf) +{ + memcpy(non_3gpp_nw_provided_policies, pkbuf->data - 1, 1); + + ogs_trace(" NON_3GPP_NW_PROVIDED_POLICIES - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_non_3gpp_nw_provided_policies(ogs_pkbuf_t *pkbuf, ogs_nas_non_3gpp_nw_provided_policies_t *non_3gpp_nw_provided_policies) +{ + uint16_t size = sizeof(ogs_nas_non_3gpp_nw_provided_policies_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, non_3gpp_nw_provided_policies, size); + + ogs_trace(" NON_3GPP_NW_PROVIDED_POLICIES - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.37 NSSAI + * O TLV 4-74 */ +int ogs_nas_decode_nssai(ogs_nas_nssai_t *nssai, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_nssai_t *source = (ogs_nas_nssai_t *)pkbuf->data; + + nssai->length = source->length; + size = nssai->length + sizeof(nssai->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(nssai, pkbuf->data - size, size); + + ogs_trace(" NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_nssai_t *nssai) +{ + uint16_t size = nssai->length + sizeof(nssai->length); + ogs_nas_nssai_t target; + + memcpy(&target, nssai, sizeof(ogs_nas_nssai_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.37A NSSAI inclusion mode + * O TV 1 */ +int ogs_nas_decode_nssai_inclusion_mode(ogs_nas_nssai_inclusion_mode_t *nssai_inclusion_mode, ogs_pkbuf_t *pkbuf) +{ + memcpy(nssai_inclusion_mode, pkbuf->data - 1, 1); + + ogs_trace(" NSSAI_INCLUSION_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_nssai_inclusion_mode(ogs_pkbuf_t *pkbuf, ogs_nas_nssai_inclusion_mode_t *nssai_inclusion_mode) +{ + uint16_t size = sizeof(ogs_nas_nssai_inclusion_mode_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, nssai_inclusion_mode, size); + + ogs_trace(" NSSAI_INCLUSION_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.38 Operator-defined access category definitions + * O TLV-E 3-n */ +int ogs_nas_decode_operator_defined_access_category_definitions(ogs_nas_operator_defined_access_category_definitions_t *operator_defined_access_category_definitions, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_operator_defined_access_category_definitions_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + operator_defined_access_category_definitions->buffer = pkbuf->data - size + sizeof(operator_defined_access_category_definitions->length); + + ogs_trace(" OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)operator_defined_access_category_definitions->buffer, operator_defined_access_category_definitions->length); + + return size; +} + +int ogs_nas_encode_operator_defined_access_category_definitions(ogs_pkbuf_t *pkbuf, ogs_nas_operator_defined_access_category_definitions_t *operator_defined_access_category_definitions) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(operator_defined_access_category_definitions); + ogs_assert(operator_defined_access_category_definitions->buffer); + + size = sizeof(operator_defined_access_category_definitions->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(operator_defined_access_category_definitions->length); + memcpy(pkbuf->data - size, &target, size); + + size = operator_defined_access_category_definitions->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, operator_defined_access_category_definitions->buffer, size); + + ogs_trace(" OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return operator_defined_access_category_definitions->length + sizeof(operator_defined_access_category_definitions->length); +} + +/* 9.11.3.39 Payload container + * O TLV-E 4-65538 */ +int ogs_nas_decode_payload_container(ogs_nas_payload_container_t *payload_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_payload_container_t *source = (ogs_nas_payload_container_t *)pkbuf->data; + + payload_container->length = be16toh(source->length); + size = payload_container->length + sizeof(payload_container->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + payload_container->buffer = pkbuf->data - size + sizeof(payload_container->length); + + ogs_trace(" PAYLOAD_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)payload_container->buffer, payload_container->length); + + return size; +} + +int ogs_nas_encode_payload_container(ogs_pkbuf_t *pkbuf, ogs_nas_payload_container_t *payload_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(payload_container); + ogs_assert(payload_container->buffer); + + size = sizeof(payload_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(payload_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = payload_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, payload_container->buffer, size); + + ogs_trace(" PAYLOAD_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return payload_container->length + sizeof(payload_container->length); +} + +/* 9.11.3.4 5GS mobile identity + * M LV-E 6-n */ +int ogs_nas_decode_5gs_mobile_identity(ogs_nas_5gs_mobile_identity_t *mobile_identity, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_mobile_identity_t *source = (ogs_nas_5gs_mobile_identity_t *)pkbuf->data; + + mobile_identity->length = source->length; + size = mobile_identity->length + sizeof(mobile_identity->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(mobile_identity, pkbuf->data - size, size); + + if (mobile_identity->guti.type == OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) { + mobile_identity->guti.m_tmsi = be32toh(mobile_identity->guti.m_tmsi); + } else if (mobile_identity->s_tmsi.type == OGS_NAS_5GS_MOBILE_IDENTITY_S_TMSI) { + mobile_identity->s_tmsi.m_tmsi = be32toh(mobile_identity->s_tmsi.m_tmsi); + } + + ogs_trace(" 5GS_MOBILE_IDENTITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_mobile_identity_t *mobile_identity) +{ + uint16_t size = mobile_identity->length + sizeof(mobile_identity->length); + ogs_nas_5gs_mobile_identity_t target; + + memcpy(&target, mobile_identity, sizeof(ogs_nas_5gs_mobile_identity_t)); + if (mobile_identity->guti.type == OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) { + target.guti.m_tmsi = htobe32(mobile_identity->guti.m_tmsi); + target.guti._0xf = 0xf; + } else if (mobile_identity->s_tmsi.type == OGS_NAS_5GS_MOBILE_IDENTITY_S_TMSI) { + target.s_tmsi.m_tmsi = htobe32(mobile_identity->s_tmsi.m_tmsi); + target.s_tmsi._0xf = 0xf; + } + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_MOBILE_IDENTITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.40 Payload container type + * O TV 1 */ +int ogs_nas_decode_payload_container_type(ogs_nas_payload_container_type_t *payload_container_type, ogs_pkbuf_t *pkbuf) +{ + memcpy(payload_container_type, pkbuf->data - 1, 1); + + ogs_trace(" PAYLOAD_CONTAINER_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_payload_container_type(ogs_pkbuf_t *pkbuf, ogs_nas_payload_container_type_t *payload_container_type) +{ + uint16_t size = sizeof(ogs_nas_payload_container_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, payload_container_type, size); + + ogs_trace(" PAYLOAD_CONTAINER_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.41 PDU session identity 2 + * C TV 2 */ +int ogs_nas_decode_pdu_session_identity_2(ogs_nas_pdu_session_identity_2_t *pdu_session_identity_2, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_pdu_session_identity_2_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pdu_session_identity_2, pkbuf->data - size, size); + + ogs_trace(" PDU_SESSION_IDENTITY_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_pdu_session_identity_2(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_identity_2_t *pdu_session_identity_2) +{ + uint16_t size = sizeof(ogs_nas_pdu_session_identity_2_t); + ogs_nas_pdu_session_identity_2_t target; + + memcpy(&target, pdu_session_identity_2, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" PDU_SESSION_IDENTITY_2 - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.42 PDU session reactivation result + * O TLV 4-34 */ +int ogs_nas_decode_pdu_session_reactivation_result(ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_pdu_session_reactivation_result_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pdu_session_reactivation_result, pkbuf->data - size, size); + + ogs_trace(" PDU_SESSION_REACTIVATION_RESULT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_pdu_session_reactivation_result(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result) +{ + uint16_t size = pdu_session_reactivation_result->length + sizeof(pdu_session_reactivation_result->length); + ogs_nas_pdu_session_reactivation_result_t target; + + memcpy(&target, pdu_session_reactivation_result, sizeof(ogs_nas_pdu_session_reactivation_result_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" PDU_SESSION_REACTIVATION_RESULT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.43 PDU session reactivation result error cause + * O TLV-E 5-515 */ +int ogs_nas_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) +{ + uint16_t size = 0; + ogs_nas_pdu_session_reactivation_result_error_cause_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + pdu_session_reactivation_result_error_cause->buffer = pkbuf->data - size + sizeof(pdu_session_reactivation_result_error_cause->length); + + ogs_trace(" PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)pdu_session_reactivation_result_error_cause->buffer, pdu_session_reactivation_result_error_cause->length); + + return size; +} + +int ogs_nas_encode_pdu_session_reactivation_result_error_cause(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_reactivation_result_error_cause_t *pdu_session_reactivation_result_error_cause) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(pdu_session_reactivation_result_error_cause); + ogs_assert(pdu_session_reactivation_result_error_cause->buffer); + + size = sizeof(pdu_session_reactivation_result_error_cause->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(pdu_session_reactivation_result_error_cause->length); + memcpy(pkbuf->data - size, &target, size); + + size = pdu_session_reactivation_result_error_cause->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, pdu_session_reactivation_result_error_cause->buffer, size); + + ogs_trace(" PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return pdu_session_reactivation_result_error_cause->length + sizeof(pdu_session_reactivation_result_error_cause->length); +} + +/* 9.11.3.44 PDU session status + * O TLV 4-34 */ +int ogs_nas_decode_pdu_session_status(ogs_nas_pdu_session_status_t *pdu_session_status, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_pdu_session_status_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pdu_session_status, pkbuf->data - size, size); + + ogs_trace(" PDU_SESSION_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_status_t *pdu_session_status) +{ + uint16_t size = pdu_session_status->length + sizeof(pdu_session_status->length); + ogs_nas_pdu_session_status_t target; + + memcpy(&target, pdu_session_status, sizeof(ogs_nas_pdu_session_status_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" PDU_SESSION_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.45 PLMN list + * O TLV 5-47 */ +int ogs_nas_decode_plmn_list(ogs_nas_plmn_list_t *plmn_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_plmn_list_t *source = (ogs_nas_plmn_list_t *)pkbuf->data; + + plmn_list->length = source->length; + size = plmn_list->length + sizeof(plmn_list->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(plmn_list, pkbuf->data - size, size); + + ogs_trace(" PLMN_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_plmn_list(ogs_pkbuf_t *pkbuf, ogs_nas_plmn_list_t *plmn_list) +{ + uint16_t size = plmn_list->length + sizeof(plmn_list->length); + ogs_nas_plmn_list_t target; + + memcpy(&target, plmn_list, sizeof(ogs_nas_plmn_list_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" PLMN_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.46 Rejected NSSAI + * O TLV 4-42 */ +int ogs_nas_decode_rejected_nssai(ogs_nas_rejected_nssai_t *rejected_nssai, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_rejected_nssai_t *source = (ogs_nas_rejected_nssai_t *)pkbuf->data; + + rejected_nssai->length = source->length; + size = rejected_nssai->length + sizeof(rejected_nssai->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(rejected_nssai, pkbuf->data - size, size); + + ogs_trace(" REJECTED_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_rejected_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_rejected_nssai_t *rejected_nssai) +{ + uint16_t size = rejected_nssai->length + sizeof(rejected_nssai->length); + ogs_nas_rejected_nssai_t target; + + memcpy(&target, rejected_nssai, sizeof(ogs_nas_rejected_nssai_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" REJECTED_NSSAI - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.46A Release assistance indication + * O TV 1 */ +int ogs_nas_decode_release_assistance_indication(ogs_nas_release_assistance_indication_t *release_assistance_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(release_assistance_indication, pkbuf->data - 1, 1); + + ogs_trace(" RELEASE_ASSISTANCE_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_release_assistance_indication(ogs_pkbuf_t *pkbuf, ogs_nas_release_assistance_indication_t *release_assistance_indication) +{ + uint16_t size = sizeof(ogs_nas_release_assistance_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, release_assistance_indication, size); + + ogs_trace(" RELEASE_ASSISTANCE_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.47 Request type + * O TV 1 */ +int ogs_nas_decode_request_type(ogs_nas_request_type_t *request_type, ogs_pkbuf_t *pkbuf) +{ + memcpy(request_type, pkbuf->data - 1, 1); + + ogs_trace(" REQUEST_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_request_type_t *request_type) +{ + uint16_t size = sizeof(ogs_nas_request_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, request_type, size); + + ogs_trace(" REQUEST_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.48 S1 UE network capability + * O TLV 4-15 */ +int ogs_nas_decode_s1_ue_network_capability(ogs_nas_s1_ue_network_capability_t *s1_ue_network_capability, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_s1_ue_network_capability_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(s1_ue_network_capability, pkbuf->data - size, size); + + ogs_trace(" S1_UE_NETWORK_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_s1_ue_network_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_ue_network_capability_t *s1_ue_network_capability) +{ + uint16_t size = s1_ue_network_capability->length + sizeof(s1_ue_network_capability->length); + ogs_nas_s1_ue_network_capability_t target; + + memcpy(&target, s1_ue_network_capability, sizeof(ogs_nas_s1_ue_network_capability_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" S1_UE_NETWORK_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.48A S1 UE security capability + * O TLV 4-7 */ +int ogs_nas_decode_s1_ue_security_capability(ogs_nas_s1_ue_security_capability_t *s1_ue_security_capability, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_s1_ue_security_capability_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(s1_ue_security_capability, pkbuf->data - size, size); + + ogs_trace(" S1_UE_SECURITY_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_s1_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_ue_security_capability_t *s1_ue_security_capability) +{ + uint16_t size = s1_ue_security_capability->length + sizeof(s1_ue_security_capability->length); + ogs_nas_s1_ue_security_capability_t target; + + memcpy(&target, s1_ue_security_capability, sizeof(ogs_nas_s1_ue_security_capability_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" S1_UE_SECURITY_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.49 Service area list + * O TLV 6-114 */ +int ogs_nas_decode_service_area_list(ogs_nas_service_area_list_t *service_area_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_service_area_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(service_area_list, pkbuf->data - size, size); + + ogs_trace(" SERVICE_AREA_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_service_area_list(ogs_pkbuf_t *pkbuf, ogs_nas_service_area_list_t *service_area_list) +{ + uint16_t size = service_area_list->length + sizeof(service_area_list->length); + ogs_nas_service_area_list_t target; + + memcpy(&target, service_area_list, sizeof(ogs_nas_service_area_list_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SERVICE_AREA_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.5 5GS network feature support + * O TLV 3-5 */ +int ogs_nas_decode_5gs_network_feature_support(ogs_nas_5gs_network_feature_support_t *network_feature_support, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_network_feature_support_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(network_feature_support, pkbuf->data - size, size); + + ogs_trace(" 5GS_NETWORK_FEATURE_SUPPORT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_network_feature_support(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_network_feature_support_t *network_feature_support) +{ + uint16_t size = network_feature_support->length + sizeof(network_feature_support->length); + ogs_nas_5gs_network_feature_support_t target; + + memcpy(&target, network_feature_support, sizeof(ogs_nas_5gs_network_feature_support_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_NETWORK_FEATURE_SUPPORT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.50A SMS indication + * O TV 1 */ +int ogs_nas_decode_sms_indication(ogs_nas_sms_indication_t *sms_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(sms_indication, pkbuf->data - 1, 1); + + ogs_trace(" SMS_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_sms_indication(ogs_pkbuf_t *pkbuf, ogs_nas_sms_indication_t *sms_indication) +{ + uint16_t size = sizeof(ogs_nas_sms_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, sms_indication, size); + + ogs_trace(" SMS_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.51 SOR transparent container + * O TLV-E 20-n */ +int ogs_nas_decode_sor_transparent_container(ogs_nas_sor_transparent_container_t *sor_transparent_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_sor_transparent_container_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + sor_transparent_container->buffer = pkbuf->data - size + sizeof(sor_transparent_container->length); + + ogs_trace(" SOR_TRANSPARENT_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)sor_transparent_container->buffer, sor_transparent_container->length); + + return size; +} + +int ogs_nas_encode_sor_transparent_container(ogs_pkbuf_t *pkbuf, ogs_nas_sor_transparent_container_t *sor_transparent_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(sor_transparent_container); + ogs_assert(sor_transparent_container->buffer); + + size = sizeof(sor_transparent_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(sor_transparent_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = sor_transparent_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, sor_transparent_container->buffer, size); + + ogs_trace(" SOR_TRANSPARENT_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return sor_transparent_container->length + sizeof(sor_transparent_container->length); +} + +/* 9.11.3.51A Supported codec list + * O TLV 5-n */ +int ogs_nas_decode_supported_codec_list(ogs_nas_supported_codec_list_t *supported_codec_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_supported_codec_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(supported_codec_list, pkbuf->data - size, size); + + ogs_trace(" SUPPORTED_CODEC_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_supported_codec_list(ogs_pkbuf_t *pkbuf, ogs_nas_supported_codec_list_t *supported_codec_list) +{ + uint16_t size = supported_codec_list->length + sizeof(supported_codec_list->length); + ogs_nas_supported_codec_list_t target; + + memcpy(&target, supported_codec_list, sizeof(ogs_nas_supported_codec_list_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SUPPORTED_CODEC_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.52 Time zone + * O TV 2 */ +int ogs_nas_decode_time_zone(ogs_nas_time_zone_t *time_zone, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_time_zone_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(time_zone, pkbuf->data - size, size); + + ogs_trace(" TIME_ZONE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_time_zone(ogs_pkbuf_t *pkbuf, ogs_nas_time_zone_t *time_zone) +{ + uint16_t size = sizeof(ogs_nas_time_zone_t); + ogs_nas_time_zone_t target; + + memcpy(&target, time_zone, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" TIME_ZONE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.53 Time zone and time + * O TV 8 */ +int ogs_nas_decode_time_zone_and_time(ogs_nas_time_zone_and_time_t *time_zone_and_time, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_time_zone_and_time_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(time_zone_and_time, pkbuf->data - size, size); + + ogs_trace(" TIME_ZONE_AND_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_time_zone_and_time(ogs_pkbuf_t *pkbuf, ogs_nas_time_zone_and_time_t *time_zone_and_time) +{ + uint16_t size = sizeof(ogs_nas_time_zone_and_time_t); + ogs_nas_time_zone_and_time_t target; + + memcpy(&target, time_zone_and_time, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" TIME_ZONE_AND_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.54 UE security capability + * O TLV 4-10 */ +int ogs_nas_decode_ue_security_capability(ogs_nas_ue_security_capability_t *ue_security_capability, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ue_security_capability_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ue_security_capability, pkbuf->data - size, size); + + ogs_trace(" UE_SECURITY_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_ue_security_capability_t *ue_security_capability) +{ + uint16_t size = ue_security_capability->length + sizeof(ue_security_capability->length); + ogs_nas_ue_security_capability_t target; + + memcpy(&target, ue_security_capability, sizeof(ogs_nas_ue_security_capability_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UE_SECURITY_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.55 UE usage setting + * O TLV 3 */ +int ogs_nas_decode_ue_usage_setting(ogs_nas_ue_usage_setting_t *ue_usage_setting, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ue_usage_setting_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ue_usage_setting, pkbuf->data - size, size); + + ogs_trace(" UE_USAGE_SETTING - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ue_usage_setting(ogs_pkbuf_t *pkbuf, ogs_nas_ue_usage_setting_t *ue_usage_setting) +{ + uint16_t size = ue_usage_setting->length + sizeof(ue_usage_setting->length); + ogs_nas_ue_usage_setting_t target; + + memcpy(&target, ue_usage_setting, sizeof(ogs_nas_ue_usage_setting_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UE_USAGE_SETTING - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.56 UE status + * O TLV 3 */ +int ogs_nas_decode_ue_status(ogs_nas_ue_status_t *ue_status, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ue_status_t *source = (ogs_nas_ue_status_t *)pkbuf->data; + + ue_status->length = source->length; + size = ue_status->length + sizeof(ue_status->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ue_status, pkbuf->data - size, size); + + ogs_trace(" UE_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ue_status(ogs_pkbuf_t *pkbuf, ogs_nas_ue_status_t *ue_status) +{ + uint16_t size = ue_status->length + sizeof(ue_status->length); + ogs_nas_ue_status_t target; + + memcpy(&target, ue_status, sizeof(ogs_nas_ue_status_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UE_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.57 Uplink data status + * O TLV 4-34 */ +int ogs_nas_decode_uplink_data_status(ogs_nas_uplink_data_status_t *uplink_data_status, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_uplink_data_status_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(uplink_data_status, pkbuf->data - size, size); + + ogs_trace(" UPLINK_DATA_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_uplink_data_status(ogs_pkbuf_t *pkbuf, ogs_nas_uplink_data_status_t *uplink_data_status) +{ + uint16_t size = uplink_data_status->length + sizeof(uplink_data_status->length); + ogs_nas_uplink_data_status_t target; + + memcpy(&target, uplink_data_status, sizeof(ogs_nas_uplink_data_status_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UPLINK_DATA_STATUS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.6 5GS registration result + * M LV 2 */ +int ogs_nas_decode_5gs_registration_result(ogs_nas_5gs_registration_result_t *registration_result, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_registration_result_t *source = (ogs_nas_5gs_registration_result_t *)pkbuf->data; + + registration_result->length = source->length; + size = registration_result->length + sizeof(registration_result->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(registration_result, pkbuf->data - size, size); + + ogs_trace(" 5GS_REGISTRATION_RESULT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_registration_result(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_registration_result_t *registration_result) +{ + uint16_t size = registration_result->length + sizeof(registration_result->length); + ogs_nas_5gs_registration_result_t target; + + memcpy(&target, registration_result, sizeof(ogs_nas_5gs_registration_result_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_REGISTRATION_RESULT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.68 UE radio capability ID + * O TLV 3-n */ +int ogs_nas_decode_ue_radio_capability_id(ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ue_radio_capability_id_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ue_radio_capability_id, pkbuf->data - size, size); + + ogs_trace(" UE_RADIO_CAPABILITY_ID - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ue_radio_capability_id(ogs_pkbuf_t *pkbuf, ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id) +{ + uint16_t size = ue_radio_capability_id->length + sizeof(ue_radio_capability_id->length); + ogs_nas_ue_radio_capability_id_t target; + + memcpy(&target, ue_radio_capability_id, sizeof(ogs_nas_ue_radio_capability_id_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UE_RADIO_CAPABILITY_ID - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.69 UE radio capability ID deletion indication + * O TV 1 */ +int ogs_nas_decode_ue_radio_capability_id_deletion_indication(ogs_nas_ue_radio_capability_id_deletion_indication_t *ue_radio_capability_id_deletion_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(ue_radio_capability_id_deletion_indication, pkbuf->data - 1, 1); + + ogs_trace(" UE_RADIO_CAPABILITY_ID_DELETION_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_ue_radio_capability_id_deletion_indication(ogs_pkbuf_t *pkbuf, ogs_nas_ue_radio_capability_id_deletion_indication_t *ue_radio_capability_id_deletion_indication) +{ + uint16_t size = sizeof(ogs_nas_ue_radio_capability_id_deletion_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ue_radio_capability_id_deletion_indication, size); + + ogs_trace(" UE_RADIO_CAPABILITY_ID_DELETION_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.7 5GS registration type + * M V 1/2 */ +int ogs_nas_decode_5gs_registration_type(ogs_nas_5gs_registration_type_t *registration_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_5gs_registration_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(registration_type, pkbuf->data - size, size); + + ogs_trace(" 5GS_REGISTRATION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_registration_type_t *registration_type) +{ + uint16_t size = sizeof(ogs_nas_5gs_registration_type_t); + ogs_nas_5gs_registration_type_t target; + + memcpy(&target, registration_type, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_REGISTRATION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.70 Truncated 5G-S-TMSI configuration + * O TLV 3 */ +int ogs_nas_decode_truncated_5g_s_tmsi_configuration(ogs_nas_truncated_5g_s_tmsi_configuration_t *truncated_s_tmsi_configuration, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_truncated_5g_s_tmsi_configuration_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(truncated_s_tmsi_configuration, pkbuf->data - size, size); + + ogs_trace(" TRUNCATED_5G_S_TMSI_CONFIGURATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_truncated_5g_s_tmsi_configuration(ogs_pkbuf_t *pkbuf, ogs_nas_truncated_5g_s_tmsi_configuration_t *truncated_s_tmsi_configuration) +{ + uint16_t size = truncated_s_tmsi_configuration->length + sizeof(truncated_s_tmsi_configuration->length); + ogs_nas_truncated_5g_s_tmsi_configuration_t target; + + memcpy(&target, truncated_s_tmsi_configuration, sizeof(ogs_nas_truncated_5g_s_tmsi_configuration_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" TRUNCATED_5G_S_TMSI_CONFIGURATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.71 WUS assistance information + * O TLV 3-n */ +int ogs_nas_decode_wus_assistance_information(ogs_nas_wus_assistance_information_t *wus_assistance_information, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_wus_assistance_information_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(wus_assistance_information, pkbuf->data - size, size); + + ogs_trace(" WUS_ASSISTANCE_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_wus_assistance_information(ogs_pkbuf_t *pkbuf, ogs_nas_wus_assistance_information_t *wus_assistance_information) +{ + uint16_t size = wus_assistance_information->length + sizeof(wus_assistance_information->length); + ogs_nas_wus_assistance_information_t target; + + memcpy(&target, wus_assistance_information, sizeof(ogs_nas_wus_assistance_information_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" WUS_ASSISTANCE_INFORMATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.72 N5GC indication + * O T 1 */ +int ogs_nas_decode_n5gc_indication(ogs_nas_n5gc_indication_t *n5gc_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(n5gc_indication, pkbuf->data - 1, 1); + + ogs_trace(" N5GC_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_n5gc_indication(ogs_pkbuf_t *pkbuf, ogs_nas_n5gc_indication_t *n5gc_indication) +{ + uint16_t size = sizeof(ogs_nas_n5gc_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, n5gc_indication, size); + + ogs_trace(" N5GC_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.8 5GS tracking area identity + * O TV 7 */ +int ogs_nas_decode_5gs_tracking_area_identity(ogs_nas_5gs_tracking_area_identity_t *tracking_area_identity, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_5gs_tracking_area_identity_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(tracking_area_identity, pkbuf->data - size, size); + + tracking_area_identity->tac = be16toh(tracking_area_identity->tac); + + ogs_trace(" 5GS_TRACKING_AREA_IDENTITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_tracking_area_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_tracking_area_identity_t *tracking_area_identity) +{ + uint16_t size = sizeof(ogs_nas_5gs_tracking_area_identity_t); + ogs_nas_5gs_tracking_area_identity_t target; + + memcpy(&target, tracking_area_identity, size); + target.tac = htobe16(tracking_area_identity->tac); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_TRACKING_AREA_IDENTITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.9 5GS tracking area identity list + * O TLV 9-114 */ +int ogs_nas_decode_5gs_tracking_area_identity_list(ogs_nas_5gs_tracking_area_identity_list_t *tracking_area_identity_list, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_tracking_area_identity_list_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(tracking_area_identity_list, pkbuf->data - size, size); + + ogs_trace(" 5GS_TRACKING_AREA_IDENTITY_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_tracking_area_identity_list(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_tracking_area_identity_list_t *tracking_area_identity_list) +{ + uint16_t size = tracking_area_identity_list->length + sizeof(tracking_area_identity_list->length); + ogs_nas_5gs_tracking_area_identity_list_t target; + + memcpy(&target, tracking_area_identity_list, sizeof(ogs_nas_5gs_tracking_area_identity_list_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_TRACKING_AREA_IDENTITY_LIST - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.3.9A 5GS update type + * O TLV 3 */ +int ogs_nas_decode_5gs_update_type(ogs_nas_5gs_update_type_t *update_type, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gs_update_type_t *source = (ogs_nas_5gs_update_type_t *)pkbuf->data; + + update_type->length = source->length; + size = update_type->length + sizeof(update_type->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(update_type, pkbuf->data - size, size); + + ogs_trace(" 5GS_UPDATE_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gs_update_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_update_type_t *update_type) +{ + uint16_t size = update_type->length + sizeof(update_type->length); + ogs_nas_5gs_update_type_t target; + + memcpy(&target, update_type, sizeof(ogs_nas_5gs_update_type_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GS_UPDATE_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.1 5GSM capability + * O TLV 3-15 */ +int ogs_nas_decode_5gsm_capability(ogs_nas_5gsm_capability_t *gsm_capability, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gsm_capability_t *source = (ogs_nas_5gsm_capability_t *)pkbuf->data; + + gsm_capability->length = source->length; + size = gsm_capability->length + sizeof(gsm_capability->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gsm_capability, pkbuf->data - size, size); + + ogs_trace(" 5GSM_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gsm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_capability_t *gsm_capability) +{ + uint16_t size = gsm_capability->length + sizeof(gsm_capability->length); + ogs_nas_5gsm_capability_t target; + + memcpy(&target, gsm_capability, sizeof(ogs_nas_5gsm_capability_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GSM_CAPABILITY - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.10 PDU address + * O TLV 7, 11 or 15 */ +int ogs_nas_decode_pdu_address(ogs_nas_pdu_address_t *pdu_address, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_pdu_address_t *source = (ogs_nas_pdu_address_t *)pkbuf->data; + + pdu_address->length = source->length; + size = pdu_address->length + sizeof(pdu_address->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pdu_address, pkbuf->data - size, size); + + ogs_trace(" PDU_ADDRESS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_pdu_address(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_address_t *pdu_address) +{ + uint16_t size = pdu_address->length + sizeof(pdu_address->length); + ogs_nas_pdu_address_t target; + + memcpy(&target, pdu_address, sizeof(ogs_nas_pdu_address_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" PDU_ADDRESS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.11 PDU session type + * O TV 1 */ +int ogs_nas_decode_pdu_session_type(ogs_nas_pdu_session_type_t *pdu_session_type, ogs_pkbuf_t *pkbuf) +{ + memcpy(pdu_session_type, pkbuf->data - 1, 1); + + ogs_trace(" PDU_SESSION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_pdu_session_type(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_type_t *pdu_session_type) +{ + uint16_t size = sizeof(ogs_nas_pdu_session_type_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, pdu_session_type, size); + + ogs_trace(" PDU_SESSION_TYPE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.12 QoS flow descriptions + * O TLV-E 6-65538 */ +int ogs_nas_decode_qos_flow_descriptions(ogs_nas_qos_flow_descriptions_t *qos_flow_descriptions, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_qos_flow_descriptions_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + qos_flow_descriptions->buffer = pkbuf->data - size + sizeof(qos_flow_descriptions->length); + + ogs_trace(" QOS_FLOW_DESCRIPTIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)qos_flow_descriptions->buffer, qos_flow_descriptions->length); + + return size; +} + +int ogs_nas_encode_qos_flow_descriptions(ogs_pkbuf_t *pkbuf, ogs_nas_qos_flow_descriptions_t *qos_flow_descriptions) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(qos_flow_descriptions); + ogs_assert(qos_flow_descriptions->buffer); + + size = sizeof(qos_flow_descriptions->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(qos_flow_descriptions->length); + memcpy(pkbuf->data - size, &target, size); + + size = qos_flow_descriptions->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, qos_flow_descriptions->buffer, size); + + ogs_trace(" QOS_FLOW_DESCRIPTIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return qos_flow_descriptions->length + sizeof(qos_flow_descriptions->length); +} + +/* 9.11.4.13 QoS rules + * M LV-E 6-65538 */ +int ogs_nas_decode_qos_rules(ogs_nas_qos_rules_t *qos_rules, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_qos_rules_t *source = (ogs_nas_qos_rules_t *)pkbuf->data; + + qos_rules->length = be16toh(source->length); + size = qos_rules->length + sizeof(qos_rules->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + qos_rules->buffer = pkbuf->data - size + sizeof(qos_rules->length); + + ogs_trace(" QOS_RULES - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)qos_rules->buffer, qos_rules->length); + + return size; +} + +int ogs_nas_encode_qos_rules(ogs_pkbuf_t *pkbuf, ogs_nas_qos_rules_t *qos_rules) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(qos_rules); + ogs_assert(qos_rules->buffer); + + size = sizeof(qos_rules->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(qos_rules->length); + memcpy(pkbuf->data - size, &target, size); + + size = qos_rules->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, qos_rules->buffer, size); + + ogs_trace(" QOS_RULES - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return qos_rules->length + sizeof(qos_rules->length); +} + +/* 9.11.4.14 Session-AMBR + * M LV 7 */ +int ogs_nas_decode_session_ambr(ogs_nas_session_ambr_t *session_ambr, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_session_ambr_t *source = (ogs_nas_session_ambr_t *)pkbuf->data; + + session_ambr->length = source->length; + size = session_ambr->length + sizeof(session_ambr->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(session_ambr, pkbuf->data - size, size); + + ogs_trace(" SESSION_AMBR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_session_ambr(ogs_pkbuf_t *pkbuf, ogs_nas_session_ambr_t *session_ambr) +{ + uint16_t size = session_ambr->length + sizeof(session_ambr->length); + ogs_nas_session_ambr_t target; + + memcpy(&target, session_ambr, sizeof(ogs_nas_session_ambr_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SESSION_AMBR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.15 SM PDU DN request container + * O TLV 3-255 */ +int ogs_nas_decode_sm_pdu_dn_request_container(ogs_nas_sm_pdu_dn_request_container_t *sm_pdu_dn_request_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_sm_pdu_dn_request_container_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(sm_pdu_dn_request_container, pkbuf->data - size, size); + + ogs_trace(" SM_PDU_DN_REQUEST_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_sm_pdu_dn_request_container(ogs_pkbuf_t *pkbuf, ogs_nas_sm_pdu_dn_request_container_t *sm_pdu_dn_request_container) +{ + uint16_t size = sm_pdu_dn_request_container->length + sizeof(sm_pdu_dn_request_container->length); + ogs_nas_sm_pdu_dn_request_container_t target; + + memcpy(&target, sm_pdu_dn_request_container, sizeof(ogs_nas_sm_pdu_dn_request_container_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SM_PDU_DN_REQUEST_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.16 SSC mode + * O TV 1 */ +int ogs_nas_decode_ssc_mode(ogs_nas_ssc_mode_t *ssc_mode, ogs_pkbuf_t *pkbuf) +{ + memcpy(ssc_mode, pkbuf->data - 1, 1); + + ogs_trace(" SSC_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_ssc_mode_t *ssc_mode) +{ + uint16_t size = sizeof(ogs_nas_ssc_mode_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, ssc_mode, size); + + ogs_trace(" SSC_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.17 Re-attempt indicator + * O TLV 3 */ +int ogs_nas_decode_re_attempt_indicator(ogs_nas_re_attempt_indicator_t *re_attempt_indicator, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_re_attempt_indicator_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(re_attempt_indicator, pkbuf->data - size, size); + + ogs_trace(" RE_ATTEMPT_INDICATOR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_re_attempt_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_re_attempt_indicator_t *re_attempt_indicator) +{ + uint16_t size = re_attempt_indicator->length + sizeof(re_attempt_indicator->length); + ogs_nas_re_attempt_indicator_t target; + + memcpy(&target, re_attempt_indicator, sizeof(ogs_nas_re_attempt_indicator_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" RE_ATTEMPT_INDICATOR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.18 5GSM network feature support + * O TLV 3-15 */ +int ogs_nas_decode_5gsm_network_feature_support(ogs_nas_5gsm_network_feature_support_t *gsm_network_feature_support, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gsm_network_feature_support_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gsm_network_feature_support, pkbuf->data - size, size); + + ogs_trace(" 5GSM_NETWORK_FEATURE_SUPPORT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gsm_network_feature_support(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_network_feature_support_t *gsm_network_feature_support) +{ + uint16_t size = gsm_network_feature_support->length + sizeof(gsm_network_feature_support->length); + ogs_nas_5gsm_network_feature_support_t target; + + memcpy(&target, gsm_network_feature_support, sizeof(ogs_nas_5gsm_network_feature_support_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GSM_NETWORK_FEATURE_SUPPORT - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.2 5GSM cause + * O TV 2 */ +int ogs_nas_decode_5gsm_cause(ogs_nas_5gsm_cause_t *gsm_cause, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_5gsm_cause_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gsm_cause, pkbuf->data - size, size); + + ogs_trace(" 5GSM_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gsm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_cause_t *gsm_cause) +{ + uint16_t size = sizeof(ogs_nas_5gsm_cause_t); + ogs_nas_5gsm_cause_t target; + + memcpy(&target, gsm_cause, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GSM_CAUSE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.20 Serving PLMN rate control + * O TLV 4 */ +int ogs_nas_decode_serving_plmn_rate_control(ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_serving_plmn_rate_control_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(serving_plmn_rate_control, pkbuf->data - size, size); + + ogs_trace(" SERVING_PLMN_RATE_CONTROL - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_serving_plmn_rate_control(ogs_pkbuf_t *pkbuf, ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control) +{ + uint16_t size = serving_plmn_rate_control->length + sizeof(serving_plmn_rate_control->length); + ogs_nas_serving_plmn_rate_control_t target; + + memcpy(&target, serving_plmn_rate_control, sizeof(ogs_nas_serving_plmn_rate_control_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" SERVING_PLMN_RATE_CONTROL - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.21 5GSM congestion re-attempt indicator + * O TLV 3 */ +int ogs_nas_decode_5gsm_congestion_re_attempt_indicator(ogs_nas_5gsm_congestion_re_attempt_indicator_t *gsm_congestion_re_attempt_indicator, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_5gsm_congestion_re_attempt_indicator_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(gsm_congestion_re_attempt_indicator, pkbuf->data - size, size); + + ogs_trace(" 5GSM_CONGESTION_RE_ATTEMPT_INDICATOR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_5gsm_congestion_re_attempt_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_congestion_re_attempt_indicator_t *gsm_congestion_re_attempt_indicator) +{ + uint16_t size = gsm_congestion_re_attempt_indicator->length + sizeof(gsm_congestion_re_attempt_indicator->length); + ogs_nas_5gsm_congestion_re_attempt_indicator_t target; + + memcpy(&target, gsm_congestion_re_attempt_indicator, sizeof(ogs_nas_5gsm_congestion_re_attempt_indicator_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" 5GSM_CONGESTION_RE_ATTEMPT_INDICATOR - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.22 ATSSS container + * O TLV-E 3-65538 */ +int ogs_nas_decode_atsss_container(ogs_nas_atsss_container_t *atsss_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_atsss_container_t *source = (ogs_nas_atsss_container_t *)pkbuf->data; + + atsss_container->length = be16toh(source->length); + size = atsss_container->length + sizeof(atsss_container->length); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + atsss_container->buffer = pkbuf->data - size + sizeof(atsss_container->length); + + ogs_trace(" ATSSS_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)atsss_container->buffer, atsss_container->length); + + return size; +} + +int ogs_nas_encode_atsss_container(ogs_pkbuf_t *pkbuf, ogs_nas_atsss_container_t *atsss_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(atsss_container); + ogs_assert(atsss_container->buffer); + + size = sizeof(atsss_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(atsss_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = atsss_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, atsss_container->buffer, size); + + ogs_trace(" ATSSS_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return atsss_container->length + sizeof(atsss_container->length); +} + +/* 9.11.4.23 Control plane only indication + * O TV 1 */ +int ogs_nas_decode_control_plane_only_indication(ogs_nas_control_plane_only_indication_t *control_plane_only_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(control_plane_only_indication, pkbuf->data - 1, 1); + + ogs_trace(" CONTROL_PLANE_ONLY_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_control_plane_only_indication(ogs_pkbuf_t *pkbuf, ogs_nas_control_plane_only_indication_t *control_plane_only_indication) +{ + uint16_t size = sizeof(ogs_nas_control_plane_only_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, control_plane_only_indication, size); + + ogs_trace(" CONTROL_PLANE_ONLY_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.24 Header compression configuration + * O TLV 5-257 */ +int ogs_nas_decode_header_compression_configuration(ogs_nas_header_compression_configuration_t *header_compression_configuration, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_header_compression_configuration_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(header_compression_configuration, pkbuf->data - size, size); + + header_compression_configuration->max_cid = be16toh(header_compression_configuration->max_cid); + + ogs_trace(" HEADER_COMPRESSION_CONFIGURATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_header_compression_configuration(ogs_pkbuf_t *pkbuf, ogs_nas_header_compression_configuration_t *header_compression_configuration) +{ + uint16_t size = header_compression_configuration->length + sizeof(header_compression_configuration->length); + ogs_nas_header_compression_configuration_t target; + + memcpy(&target, header_compression_configuration, sizeof(ogs_nas_header_compression_configuration_t)); + target.max_cid = htobe16(header_compression_configuration->max_cid); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" HEADER_COMPRESSION_CONFIGURATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.25 DS-TT Ethernet port MAC address + * O TLV 8 */ +int ogs_nas_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) +{ + uint16_t size = 0; + ogs_nas_ds_tt_ethernet_port_mac_address_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ds_tt_ethernet_port_mac_address, pkbuf->data - size, size); + + ogs_trace(" DS_TT_ETHERNET_PORT_MAC_ADDRESS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ds_tt_ethernet_port_mac_address(ogs_pkbuf_t *pkbuf, ogs_nas_ds_tt_ethernet_port_mac_address_t *ds_tt_ethernet_port_mac_address) +{ + uint16_t size = ds_tt_ethernet_port_mac_address->length + sizeof(ds_tt_ethernet_port_mac_address->length); + ogs_nas_ds_tt_ethernet_port_mac_address_t target; + + memcpy(&target, ds_tt_ethernet_port_mac_address, sizeof(ogs_nas_ds_tt_ethernet_port_mac_address_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" DS_TT_ETHERNET_PORT_MAC_ADDRESS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.26 UE-DS-TT residence time + * O TLV 10 */ +int ogs_nas_decode_ue_ds_tt_residence_time(ogs_nas_ue_ds_tt_residence_time_t *ue_ds_tt_residence_time, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_ue_ds_tt_residence_time_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(ue_ds_tt_residence_time, pkbuf->data - size, size); + + ogs_trace(" UE_DS_TT_RESIDENCE_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_ue_ds_tt_residence_time(ogs_pkbuf_t *pkbuf, ogs_nas_ue_ds_tt_residence_time_t *ue_ds_tt_residence_time) +{ + uint16_t size = ue_ds_tt_residence_time->length + sizeof(ue_ds_tt_residence_time->length); + ogs_nas_ue_ds_tt_residence_time_t target; + + memcpy(&target, ue_ds_tt_residence_time, sizeof(ogs_nas_ue_ds_tt_residence_time_t)); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" UE_DS_TT_RESIDENCE_TIME - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.27 Port management information container + * O TLV-E 4-65538 */ +int ogs_nas_decode_port_management_information_container(ogs_nas_port_management_information_container_t *port_management_information_container, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_port_management_information_container_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + port_management_information_container->buffer = pkbuf->data - size + sizeof(port_management_information_container->length); + + ogs_trace(" PORT_MANAGEMENT_INFORMATION_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)port_management_information_container->buffer, port_management_information_container->length); + + return size; +} + +int ogs_nas_encode_port_management_information_container(ogs_pkbuf_t *pkbuf, ogs_nas_port_management_information_container_t *port_management_information_container) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(port_management_information_container); + ogs_assert(port_management_information_container->buffer); + + size = sizeof(port_management_information_container->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(port_management_information_container->length); + memcpy(pkbuf->data - size, &target, size); + + size = port_management_information_container->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, port_management_information_container->buffer, size); + + ogs_trace(" PORT_MANAGEMENT_INFORMATION_CONTAINER - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return port_management_information_container->length + sizeof(port_management_information_container->length); +} + +/* 9.11.4.3 Always-on PDU session indication + * O TV 1 */ +int ogs_nas_decode_always_on_pdu_session_indication(ogs_nas_always_on_pdu_session_indication_t *always_on_pdu_session_indication, ogs_pkbuf_t *pkbuf) +{ + memcpy(always_on_pdu_session_indication, pkbuf->data - 1, 1); + + ogs_trace(" ALWAYS_ON_PDU_SESSION_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_always_on_pdu_session_indication(ogs_pkbuf_t *pkbuf, ogs_nas_always_on_pdu_session_indication_t *always_on_pdu_session_indication) +{ + uint16_t size = sizeof(ogs_nas_always_on_pdu_session_indication_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, always_on_pdu_session_indication, size); + + ogs_trace(" ALWAYS_ON_PDU_SESSION_INDICATION - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.4 Always-on PDU session requested + * O TV 1 */ +int ogs_nas_decode_always_on_pdu_session_requested(ogs_nas_always_on_pdu_session_requested_t *always_on_pdu_session_requested, ogs_pkbuf_t *pkbuf) +{ + memcpy(always_on_pdu_session_requested, pkbuf->data - 1, 1); + + ogs_trace(" ALWAYS_ON_PDU_SESSION_REQUESTED - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_always_on_pdu_session_requested(ogs_pkbuf_t *pkbuf, ogs_nas_always_on_pdu_session_requested_t *always_on_pdu_session_requested) +{ + uint16_t size = sizeof(ogs_nas_always_on_pdu_session_requested_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, always_on_pdu_session_requested, size); + + ogs_trace(" ALWAYS_ON_PDU_SESSION_REQUESTED - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.5 Allowed SSC mode + * O TV 1 */ +int ogs_nas_decode_allowed_ssc_mode(ogs_nas_allowed_ssc_mode_t *allowed_ssc_mode, ogs_pkbuf_t *pkbuf) +{ + memcpy(allowed_ssc_mode, pkbuf->data - 1, 1); + + ogs_trace(" ALLOWED_SSC_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1); + + return 0; +} + +int ogs_nas_encode_allowed_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_allowed_ssc_mode_t *allowed_ssc_mode) +{ + uint16_t size = sizeof(ogs_nas_allowed_ssc_mode_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, allowed_ssc_mode, size); + + ogs_trace(" ALLOWED_SSC_MODE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.6 Extended protocol configuration options + * O TLV-E 4-65538 */ +int ogs_nas_decode_extended_protocol_configuration_options(ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_extended_protocol_configuration_options_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + extended_protocol_configuration_options->buffer = pkbuf->data - size + sizeof(extended_protocol_configuration_options->length); + + ogs_trace(" EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)extended_protocol_configuration_options->buffer, extended_protocol_configuration_options->length); + + return size; +} + +int ogs_nas_encode_extended_protocol_configuration_options(ogs_pkbuf_t *pkbuf, ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(extended_protocol_configuration_options); + ogs_assert(extended_protocol_configuration_options->buffer); + + size = sizeof(extended_protocol_configuration_options->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(extended_protocol_configuration_options->length); + memcpy(pkbuf->data - size, &target, size); + + size = extended_protocol_configuration_options->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, extended_protocol_configuration_options->buffer, size); + + ogs_trace(" EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return extended_protocol_configuration_options->length + sizeof(extended_protocol_configuration_options->length); +} + +/* 9.11.4.7 Integrity protection maximum data rate + * M V 2 */ +int ogs_nas_decode_integrity_protection_maximum_data_rate(ogs_nas_integrity_protection_maximum_data_rate_t *integrity_protection_maximum_data_rate, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_integrity_protection_maximum_data_rate_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(integrity_protection_maximum_data_rate, pkbuf->data - size, size); + + ogs_trace(" INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_integrity_protection_maximum_data_rate(ogs_pkbuf_t *pkbuf, ogs_nas_integrity_protection_maximum_data_rate_t *integrity_protection_maximum_data_rate) +{ + uint16_t size = sizeof(ogs_nas_integrity_protection_maximum_data_rate_t); + ogs_nas_integrity_protection_maximum_data_rate_t target; + + memcpy(&target, integrity_protection_maximum_data_rate, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +/* 9.11.4.8 Mapped EPS bearer contexts + * O TLV-E 7-65538 */ +int ogs_nas_decode_mapped_eps_bearer_contexts(ogs_nas_mapped_eps_bearer_contexts_t *mapped_eps_bearer_contexts, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = 0; + ogs_nas_mapped_eps_bearer_contexts_t *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); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + mapped_eps_bearer_contexts->buffer = pkbuf->data - size + sizeof(mapped_eps_bearer_contexts->length); + + ogs_trace(" MAPPED_EPS_BEARER_CONTEXTS - "); + ogs_log_hexdump(OGS_LOG_TRACE, (void*)mapped_eps_bearer_contexts->buffer, mapped_eps_bearer_contexts->length); + + return size; +} + +int ogs_nas_encode_mapped_eps_bearer_contexts(ogs_pkbuf_t *pkbuf, ogs_nas_mapped_eps_bearer_contexts_t *mapped_eps_bearer_contexts) +{ + uint16_t size = 0; + uint16_t target; + + ogs_assert(mapped_eps_bearer_contexts); + ogs_assert(mapped_eps_bearer_contexts->buffer); + + size = sizeof(mapped_eps_bearer_contexts->length); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + target = htobe16(mapped_eps_bearer_contexts->length); + memcpy(pkbuf->data - size, &target, size); + + size = mapped_eps_bearer_contexts->length; + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, mapped_eps_bearer_contexts->buffer, size); + + ogs_trace(" MAPPED_EPS_BEARER_CONTEXTS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return mapped_eps_bearer_contexts->length + sizeof(mapped_eps_bearer_contexts->length); +} + +/* 9.11.4.9 Maximum number of supported packet filters + * O TV 3 */ +int ogs_nas_decode_maximum_number_of_supported_packet_filters(ogs_nas_maximum_number_of_supported_packet_filters_t *maximum_number_of_supported_packet_filters, ogs_pkbuf_t *pkbuf) +{ + uint16_t size = sizeof(ogs_nas_maximum_number_of_supported_packet_filters_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(maximum_number_of_supported_packet_filters, pkbuf->data - size, size); + + ogs_trace(" MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + +int ogs_nas_encode_maximum_number_of_supported_packet_filters(ogs_pkbuf_t *pkbuf, ogs_nas_maximum_number_of_supported_packet_filters_t *maximum_number_of_supported_packet_filters) +{ + uint16_t size = sizeof(ogs_nas_maximum_number_of_supported_packet_filters_t); + ogs_nas_maximum_number_of_supported_packet_filters_t target; + + memcpy(&target, maximum_number_of_supported_packet_filters, size); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &target, size); + + ogs_trace(" MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS - "); + ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size); + + return size; +} + diff --git a/lib/nas/5gs/ies.h b/lib/nas/5gs/ies.h new file mode 100644 index 000000000..4696ac722 --- /dev/null +++ b/lib/nas/5gs/ies.h @@ -0,0 +1,273 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 21:20:09.020951 by acetcom + * from 24501-g41.docx + ******************************************************************************/ + +#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_5GS_IES_H +#define OGS_NAS_5GS_IES_H + +#ifdef __cplusplus +extern "C" { +#endif + +int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type); + +int ogs_nas_decode_additional_information(ogs_nas_additional_information_t *additional_information, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_access_type(ogs_nas_access_type_t *access_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_dnn(ogs_nas_dnn_t *dnn, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_eap_message(ogs_nas_eap_message_t *eap_message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_gprs_timer(ogs_nas_gprs_timer_t *gprs_timer, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_gprs_timer_2(ogs_nas_gprs_timer_2_t *gprs_timer_2, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_gprs_timer_3(ogs_nas_gprs_timer_3_t *gprs_timer_3, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_s_nssai(ogs_nas_s_nssai_t *s_nssai, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gmm_capability(ogs_nas_5gmm_capability_t *gmm_capability, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_abba(ogs_nas_abba_t *abba, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_additional_5g_security_information(ogs_nas_additional_5g_security_information_t *additional_security_information, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_additional_information_requested(ogs_nas_additional_information_requested_t *additional_information_requested, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_allowed_pdu_session_status(ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_failure_parameter(ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_parameter_autn(ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_parameter_rand(ogs_nas_authentication_parameter_rand_t *authentication_parameter_rand, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_response_parameter(ogs_nas_authentication_response_parameter_t *authentication_response_parameter, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_configuration_update_indication(ogs_nas_configuration_update_indication_t *configuration_update_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_cag_information_list(ogs_nas_cag_information_list_t *cag_information_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ciot_small_data_container(ogs_nas_ciot_small_data_container_t *ciot_small_data_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ciphering_key_data(ogs_nas_ciphering_key_data_t *ciphering_key_data, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_control_plane_service_type(ogs_nas_control_plane_service_type_t *control_plane_service_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_daylight_saving_time(ogs_nas_daylight_saving_time_t *daylight_saving_time, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gmm_cause(ogs_nas_5gmm_cause_t *gmm_cause, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_de_registration_type(ogs_nas_de_registration_type_t *de_registration_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_emergency_number_list(ogs_nas_emergency_number_list_t *emergency_number_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_eps_bearer_context_status(ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_eps_nas_message_container(ogs_nas_eps_nas_message_container_t *eps_nas_message_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_eps_nas_security_algorithms(ogs_nas_eps_nas_security_algorithms_t *eps_nas_security_algorithms, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_extended_emergency_number_list(ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_extended_drx_parameters(ogs_nas_extended_drx_parameters_t *extended_drx_parameters, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_imeisv_request(ogs_nas_imeisv_request_t *imeisv_request, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ladn_indication(ogs_nas_ladn_indication_t *ladn_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_drx_parameters(ogs_nas_5gs_drx_parameters_t *drx_parameters, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_identity_type(ogs_nas_5gs_identity_type_t *identity_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ladn_information(ogs_nas_ladn_information_t *ladn_information, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_mico_indication(ogs_nas_mico_indication_t *mico_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ma_pdu_session_information(ogs_nas_ma_pdu_session_information_t *ma_pdu_session_information, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_mapped_nssai(ogs_nas_mapped_nssai_t *mapped_nssai, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_mobile_station_classmark_2(ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_key_set_identifier(ogs_nas_key_set_identifier_t *key_set_identifier, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_message_container(ogs_nas_message_container_t *message_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_algorithms(ogs_nas_security_algorithms_t *security_algorithms, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_network_name(ogs_nas_network_name_t *network_name, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_network_slicing_indication(ogs_nas_network_slicing_indication_t *network_slicing_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_non_3gpp_nw_provided_policies(ogs_nas_non_3gpp_nw_provided_policies_t *non_3gpp_nw_provided_policies, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_nssai(ogs_nas_nssai_t *nssai, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_nssai_inclusion_mode(ogs_nas_nssai_inclusion_mode_t *nssai_inclusion_mode, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_operator_defined_access_category_definitions(ogs_nas_operator_defined_access_category_definitions_t *operator_defined_access_category_definitions, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_payload_container(ogs_nas_payload_container_t *payload_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_mobile_identity(ogs_nas_5gs_mobile_identity_t *mobile_identity, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_payload_container_type(ogs_nas_payload_container_type_t *payload_container_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_identity_2(ogs_nas_pdu_session_identity_2_t *pdu_session_identity_2, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_reactivation_result(ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result, ogs_pkbuf_t *pkbuf); +int ogs_nas_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 ogs_nas_decode_pdu_session_status(ogs_nas_pdu_session_status_t *pdu_session_status, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_plmn_list(ogs_nas_plmn_list_t *plmn_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_rejected_nssai(ogs_nas_rejected_nssai_t *rejected_nssai, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_release_assistance_indication(ogs_nas_release_assistance_indication_t *release_assistance_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_request_type(ogs_nas_request_type_t *request_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_s1_ue_network_capability(ogs_nas_s1_ue_network_capability_t *s1_ue_network_capability, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_s1_ue_security_capability(ogs_nas_s1_ue_security_capability_t *s1_ue_security_capability, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_area_list(ogs_nas_service_area_list_t *service_area_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_network_feature_support(ogs_nas_5gs_network_feature_support_t *network_feature_support, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_sms_indication(ogs_nas_sms_indication_t *sms_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_sor_transparent_container(ogs_nas_sor_transparent_container_t *sor_transparent_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_supported_codec_list(ogs_nas_supported_codec_list_t *supported_codec_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_time_zone(ogs_nas_time_zone_t *time_zone, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_time_zone_and_time(ogs_nas_time_zone_and_time_t *time_zone_and_time, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ue_security_capability(ogs_nas_ue_security_capability_t *ue_security_capability, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ue_usage_setting(ogs_nas_ue_usage_setting_t *ue_usage_setting, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ue_status(ogs_nas_ue_status_t *ue_status, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_uplink_data_status(ogs_nas_uplink_data_status_t *uplink_data_status, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_registration_result(ogs_nas_5gs_registration_result_t *registration_result, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ue_radio_capability_id(ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ue_radio_capability_id_deletion_indication(ogs_nas_ue_radio_capability_id_deletion_indication_t *ue_radio_capability_id_deletion_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_registration_type(ogs_nas_5gs_registration_type_t *registration_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_truncated_5g_s_tmsi_configuration(ogs_nas_truncated_5g_s_tmsi_configuration_t *truncated_s_tmsi_configuration, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_wus_assistance_information(ogs_nas_wus_assistance_information_t *wus_assistance_information, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_n5gc_indication(ogs_nas_n5gc_indication_t *n5gc_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_tracking_area_identity(ogs_nas_5gs_tracking_area_identity_t *tracking_area_identity, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_tracking_area_identity_list(ogs_nas_5gs_tracking_area_identity_list_t *tracking_area_identity_list, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gs_update_type(ogs_nas_5gs_update_type_t *update_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gsm_capability(ogs_nas_5gsm_capability_t *gsm_capability, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_address(ogs_nas_pdu_address_t *pdu_address, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdu_session_type(ogs_nas_pdu_session_type_t *pdu_session_type, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_qos_flow_descriptions(ogs_nas_qos_flow_descriptions_t *qos_flow_descriptions, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_qos_rules(ogs_nas_qos_rules_t *qos_rules, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_session_ambr(ogs_nas_session_ambr_t *session_ambr, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_sm_pdu_dn_request_container(ogs_nas_sm_pdu_dn_request_container_t *sm_pdu_dn_request_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_ssc_mode(ogs_nas_ssc_mode_t *ssc_mode, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_re_attempt_indicator(ogs_nas_re_attempt_indicator_t *re_attempt_indicator, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gsm_network_feature_support(ogs_nas_5gsm_network_feature_support_t *gsm_network_feature_support, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gsm_cause(ogs_nas_5gsm_cause_t *gsm_cause, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_serving_plmn_rate_control(ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_5gsm_congestion_re_attempt_indicator(ogs_nas_5gsm_congestion_re_attempt_indicator_t *gsm_congestion_re_attempt_indicator, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_atsss_container(ogs_nas_atsss_container_t *atsss_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_control_plane_only_indication(ogs_nas_control_plane_only_indication_t *control_plane_only_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_header_compression_configuration(ogs_nas_header_compression_configuration_t *header_compression_configuration, ogs_pkbuf_t *pkbuf); +int ogs_nas_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 ogs_nas_decode_ue_ds_tt_residence_time(ogs_nas_ue_ds_tt_residence_time_t *ue_ds_tt_residence_time, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_port_management_information_container(ogs_nas_port_management_information_container_t *port_management_information_container, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_always_on_pdu_session_indication(ogs_nas_always_on_pdu_session_indication_t *always_on_pdu_session_indication, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_always_on_pdu_session_requested(ogs_nas_always_on_pdu_session_requested_t *always_on_pdu_session_requested, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_allowed_ssc_mode(ogs_nas_allowed_ssc_mode_t *allowed_ssc_mode, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_extended_protocol_configuration_options(ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_integrity_protection_maximum_data_rate(ogs_nas_integrity_protection_maximum_data_rate_t *integrity_protection_maximum_data_rate, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_mapped_eps_bearer_contexts(ogs_nas_mapped_eps_bearer_contexts_t *mapped_eps_bearer_contexts, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_maximum_number_of_supported_packet_filters(ogs_nas_maximum_number_of_supported_packet_filters_t *maximum_number_of_supported_packet_filters, ogs_pkbuf_t *pkbuf); + +int ogs_nas_encode_additional_information(ogs_pkbuf_t *pkbuf, ogs_nas_additional_information_t *additional_information); +int ogs_nas_encode_access_type(ogs_pkbuf_t *pkbuf, ogs_nas_access_type_t *access_type); +int ogs_nas_encode_dnn(ogs_pkbuf_t *pkbuf, ogs_nas_dnn_t *dnn); +int ogs_nas_encode_eap_message(ogs_pkbuf_t *pkbuf, ogs_nas_eap_message_t *eap_message); +int ogs_nas_encode_gprs_timer(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_t *gprs_timer); +int ogs_nas_encode_gprs_timer_2(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_2_t *gprs_timer_2); +int ogs_nas_encode_gprs_timer_3(ogs_pkbuf_t *pkbuf, ogs_nas_gprs_timer_3_t *gprs_timer_3); +int ogs_nas_encode_s_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_s_nssai_t *s_nssai); +int ogs_nas_encode_5gmm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gmm_capability_t *gmm_capability); +int ogs_nas_encode_abba(ogs_pkbuf_t *pkbuf, ogs_nas_abba_t *abba); +int ogs_nas_encode_additional_5g_security_information(ogs_pkbuf_t *pkbuf, ogs_nas_additional_5g_security_information_t *additional_security_information); +int ogs_nas_encode_additional_information_requested(ogs_pkbuf_t *pkbuf, ogs_nas_additional_information_requested_t *additional_information_requested); +int ogs_nas_encode_allowed_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status); +int ogs_nas_encode_authentication_failure_parameter(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_failure_parameter_t *authentication_failure_parameter); +int ogs_nas_encode_authentication_parameter_autn(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_parameter_autn_t *authentication_parameter_autn); +int ogs_nas_encode_authentication_parameter_rand(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_parameter_rand_t *authentication_parameter_rand); +int ogs_nas_encode_authentication_response_parameter(ogs_pkbuf_t *pkbuf, ogs_nas_authentication_response_parameter_t *authentication_response_parameter); +int ogs_nas_encode_configuration_update_indication(ogs_pkbuf_t *pkbuf, ogs_nas_configuration_update_indication_t *configuration_update_indication); +int ogs_nas_encode_cag_information_list(ogs_pkbuf_t *pkbuf, ogs_nas_cag_information_list_t *cag_information_list); +int ogs_nas_encode_ciot_small_data_container(ogs_pkbuf_t *pkbuf, ogs_nas_ciot_small_data_container_t *ciot_small_data_container); +int ogs_nas_encode_ciphering_key_data(ogs_pkbuf_t *pkbuf, ogs_nas_ciphering_key_data_t *ciphering_key_data); +int ogs_nas_encode_control_plane_service_type(ogs_pkbuf_t *pkbuf, ogs_nas_control_plane_service_type_t *control_plane_service_type); +int ogs_nas_encode_daylight_saving_time(ogs_pkbuf_t *pkbuf, ogs_nas_daylight_saving_time_t *daylight_saving_time); +int ogs_nas_encode_5gmm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_5gmm_cause_t *gmm_cause); +int ogs_nas_encode_de_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_de_registration_type_t *de_registration_type); +int ogs_nas_encode_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_emergency_number_list_t *emergency_number_list); +int ogs_nas_encode_eps_bearer_context_status(ogs_pkbuf_t *pkbuf, ogs_nas_eps_bearer_context_status_t *eps_bearer_context_status); +int ogs_nas_encode_eps_nas_message_container(ogs_pkbuf_t *pkbuf, ogs_nas_eps_nas_message_container_t *eps_nas_message_container); +int ogs_nas_encode_eps_nas_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_eps_nas_security_algorithms_t *eps_nas_security_algorithms); +int ogs_nas_encode_extended_emergency_number_list(ogs_pkbuf_t *pkbuf, ogs_nas_extended_emergency_number_list_t *extended_emergency_number_list); +int ogs_nas_encode_extended_drx_parameters(ogs_pkbuf_t *pkbuf, ogs_nas_extended_drx_parameters_t *extended_drx_parameters); +int ogs_nas_encode_imeisv_request(ogs_pkbuf_t *pkbuf, ogs_nas_imeisv_request_t *imeisv_request); +int ogs_nas_encode_ladn_indication(ogs_pkbuf_t *pkbuf, ogs_nas_ladn_indication_t *ladn_indication); +int ogs_nas_encode_5gs_drx_parameters(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_drx_parameters_t *drx_parameters); +int ogs_nas_encode_5gs_identity_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_identity_type_t *identity_type); +int ogs_nas_encode_ladn_information(ogs_pkbuf_t *pkbuf, ogs_nas_ladn_information_t *ladn_information); +int ogs_nas_encode_mico_indication(ogs_pkbuf_t *pkbuf, ogs_nas_mico_indication_t *mico_indication); +int ogs_nas_encode_ma_pdu_session_information(ogs_pkbuf_t *pkbuf, ogs_nas_ma_pdu_session_information_t *ma_pdu_session_information); +int ogs_nas_encode_mapped_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_mapped_nssai_t *mapped_nssai); +int ogs_nas_encode_mobile_station_classmark_2(ogs_pkbuf_t *pkbuf, ogs_nas_mobile_station_classmark_2_t *mobile_station_classmark_2); +int ogs_nas_encode_key_set_identifier(ogs_pkbuf_t *pkbuf, ogs_nas_key_set_identifier_t *key_set_identifier); +int ogs_nas_encode_message_container(ogs_pkbuf_t *pkbuf, ogs_nas_message_container_t *message_container); +int ogs_nas_encode_security_algorithms(ogs_pkbuf_t *pkbuf, ogs_nas_security_algorithms_t *security_algorithms); +int ogs_nas_encode_network_name(ogs_pkbuf_t *pkbuf, ogs_nas_network_name_t *network_name); +int ogs_nas_encode_network_slicing_indication(ogs_pkbuf_t *pkbuf, ogs_nas_network_slicing_indication_t *network_slicing_indication); +int ogs_nas_encode_non_3gpp_nw_provided_policies(ogs_pkbuf_t *pkbuf, ogs_nas_non_3gpp_nw_provided_policies_t *non_3gpp_nw_provided_policies); +int ogs_nas_encode_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_nssai_t *nssai); +int ogs_nas_encode_nssai_inclusion_mode(ogs_pkbuf_t *pkbuf, ogs_nas_nssai_inclusion_mode_t *nssai_inclusion_mode); +int ogs_nas_encode_operator_defined_access_category_definitions(ogs_pkbuf_t *pkbuf, ogs_nas_operator_defined_access_category_definitions_t *operator_defined_access_category_definitions); +int ogs_nas_encode_payload_container(ogs_pkbuf_t *pkbuf, ogs_nas_payload_container_t *payload_container); +int ogs_nas_encode_5gs_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_mobile_identity_t *mobile_identity); +int ogs_nas_encode_payload_container_type(ogs_pkbuf_t *pkbuf, ogs_nas_payload_container_type_t *payload_container_type); +int ogs_nas_encode_pdu_session_identity_2(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_identity_2_t *pdu_session_identity_2); +int ogs_nas_encode_pdu_session_reactivation_result(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result); +int ogs_nas_encode_pdu_session_reactivation_result_error_cause(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_reactivation_result_error_cause_t *pdu_session_reactivation_result_error_cause); +int ogs_nas_encode_pdu_session_status(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_status_t *pdu_session_status); +int ogs_nas_encode_plmn_list(ogs_pkbuf_t *pkbuf, ogs_nas_plmn_list_t *plmn_list); +int ogs_nas_encode_rejected_nssai(ogs_pkbuf_t *pkbuf, ogs_nas_rejected_nssai_t *rejected_nssai); +int ogs_nas_encode_release_assistance_indication(ogs_pkbuf_t *pkbuf, ogs_nas_release_assistance_indication_t *release_assistance_indication); +int ogs_nas_encode_request_type(ogs_pkbuf_t *pkbuf, ogs_nas_request_type_t *request_type); +int ogs_nas_encode_s1_ue_network_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_ue_network_capability_t *s1_ue_network_capability); +int ogs_nas_encode_s1_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_s1_ue_security_capability_t *s1_ue_security_capability); +int ogs_nas_encode_service_area_list(ogs_pkbuf_t *pkbuf, ogs_nas_service_area_list_t *service_area_list); +int ogs_nas_encode_5gs_network_feature_support(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_network_feature_support_t *network_feature_support); +int ogs_nas_encode_sms_indication(ogs_pkbuf_t *pkbuf, ogs_nas_sms_indication_t *sms_indication); +int ogs_nas_encode_sor_transparent_container(ogs_pkbuf_t *pkbuf, ogs_nas_sor_transparent_container_t *sor_transparent_container); +int ogs_nas_encode_supported_codec_list(ogs_pkbuf_t *pkbuf, ogs_nas_supported_codec_list_t *supported_codec_list); +int ogs_nas_encode_time_zone(ogs_pkbuf_t *pkbuf, ogs_nas_time_zone_t *time_zone); +int ogs_nas_encode_time_zone_and_time(ogs_pkbuf_t *pkbuf, ogs_nas_time_zone_and_time_t *time_zone_and_time); +int ogs_nas_encode_ue_security_capability(ogs_pkbuf_t *pkbuf, ogs_nas_ue_security_capability_t *ue_security_capability); +int ogs_nas_encode_ue_usage_setting(ogs_pkbuf_t *pkbuf, ogs_nas_ue_usage_setting_t *ue_usage_setting); +int ogs_nas_encode_ue_status(ogs_pkbuf_t *pkbuf, ogs_nas_ue_status_t *ue_status); +int ogs_nas_encode_uplink_data_status(ogs_pkbuf_t *pkbuf, ogs_nas_uplink_data_status_t *uplink_data_status); +int ogs_nas_encode_5gs_registration_result(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_registration_result_t *registration_result); +int ogs_nas_encode_ue_radio_capability_id(ogs_pkbuf_t *pkbuf, ogs_nas_ue_radio_capability_id_t *ue_radio_capability_id); +int ogs_nas_encode_ue_radio_capability_id_deletion_indication(ogs_pkbuf_t *pkbuf, ogs_nas_ue_radio_capability_id_deletion_indication_t *ue_radio_capability_id_deletion_indication); +int ogs_nas_encode_5gs_registration_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_registration_type_t *registration_type); +int ogs_nas_encode_truncated_5g_s_tmsi_configuration(ogs_pkbuf_t *pkbuf, ogs_nas_truncated_5g_s_tmsi_configuration_t *truncated_s_tmsi_configuration); +int ogs_nas_encode_wus_assistance_information(ogs_pkbuf_t *pkbuf, ogs_nas_wus_assistance_information_t *wus_assistance_information); +int ogs_nas_encode_n5gc_indication(ogs_pkbuf_t *pkbuf, ogs_nas_n5gc_indication_t *n5gc_indication); +int ogs_nas_encode_5gs_tracking_area_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_tracking_area_identity_t *tracking_area_identity); +int ogs_nas_encode_5gs_tracking_area_identity_list(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_tracking_area_identity_list_t *tracking_area_identity_list); +int ogs_nas_encode_5gs_update_type(ogs_pkbuf_t *pkbuf, ogs_nas_5gs_update_type_t *update_type); +int ogs_nas_encode_5gsm_capability(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_capability_t *gsm_capability); +int ogs_nas_encode_pdu_address(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_address_t *pdu_address); +int ogs_nas_encode_pdu_session_type(ogs_pkbuf_t *pkbuf, ogs_nas_pdu_session_type_t *pdu_session_type); +int ogs_nas_encode_qos_flow_descriptions(ogs_pkbuf_t *pkbuf, ogs_nas_qos_flow_descriptions_t *qos_flow_descriptions); +int ogs_nas_encode_qos_rules(ogs_pkbuf_t *pkbuf, ogs_nas_qos_rules_t *qos_rules); +int ogs_nas_encode_session_ambr(ogs_pkbuf_t *pkbuf, ogs_nas_session_ambr_t *session_ambr); +int ogs_nas_encode_sm_pdu_dn_request_container(ogs_pkbuf_t *pkbuf, ogs_nas_sm_pdu_dn_request_container_t *sm_pdu_dn_request_container); +int ogs_nas_encode_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_ssc_mode_t *ssc_mode); +int ogs_nas_encode_re_attempt_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_re_attempt_indicator_t *re_attempt_indicator); +int ogs_nas_encode_5gsm_network_feature_support(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_network_feature_support_t *gsm_network_feature_support); +int ogs_nas_encode_5gsm_cause(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_cause_t *gsm_cause); +int ogs_nas_encode_serving_plmn_rate_control(ogs_pkbuf_t *pkbuf, ogs_nas_serving_plmn_rate_control_t *serving_plmn_rate_control); +int ogs_nas_encode_5gsm_congestion_re_attempt_indicator(ogs_pkbuf_t *pkbuf, ogs_nas_5gsm_congestion_re_attempt_indicator_t *gsm_congestion_re_attempt_indicator); +int ogs_nas_encode_atsss_container(ogs_pkbuf_t *pkbuf, ogs_nas_atsss_container_t *atsss_container); +int ogs_nas_encode_control_plane_only_indication(ogs_pkbuf_t *pkbuf, ogs_nas_control_plane_only_indication_t *control_plane_only_indication); +int ogs_nas_encode_header_compression_configuration(ogs_pkbuf_t *pkbuf, ogs_nas_header_compression_configuration_t *header_compression_configuration); +int ogs_nas_encode_ds_tt_ethernet_port_mac_address(ogs_pkbuf_t *pkbuf, ogs_nas_ds_tt_ethernet_port_mac_address_t *ds_tt_ethernet_port_mac_address); +int ogs_nas_encode_ue_ds_tt_residence_time(ogs_pkbuf_t *pkbuf, ogs_nas_ue_ds_tt_residence_time_t *ue_ds_tt_residence_time); +int ogs_nas_encode_port_management_information_container(ogs_pkbuf_t *pkbuf, ogs_nas_port_management_information_container_t *port_management_information_container); +int ogs_nas_encode_always_on_pdu_session_indication(ogs_pkbuf_t *pkbuf, ogs_nas_always_on_pdu_session_indication_t *always_on_pdu_session_indication); +int ogs_nas_encode_always_on_pdu_session_requested(ogs_pkbuf_t *pkbuf, ogs_nas_always_on_pdu_session_requested_t *always_on_pdu_session_requested); +int ogs_nas_encode_allowed_ssc_mode(ogs_pkbuf_t *pkbuf, ogs_nas_allowed_ssc_mode_t *allowed_ssc_mode); +int ogs_nas_encode_extended_protocol_configuration_options(ogs_pkbuf_t *pkbuf, ogs_nas_extended_protocol_configuration_options_t *extended_protocol_configuration_options); +int ogs_nas_encode_integrity_protection_maximum_data_rate(ogs_pkbuf_t *pkbuf, ogs_nas_integrity_protection_maximum_data_rate_t *integrity_protection_maximum_data_rate); +int ogs_nas_encode_mapped_eps_bearer_contexts(ogs_pkbuf_t *pkbuf, ogs_nas_mapped_eps_bearer_contexts_t *mapped_eps_bearer_contexts); +int ogs_nas_encode_maximum_number_of_supported_packet_filters(ogs_pkbuf_t *pkbuf, ogs_nas_maximum_number_of_supported_packet_filters_t *maximum_number_of_supported_packet_filters); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_IES_H */ + diff --git a/lib/nas/5gs/meson.build b/lib/nas/5gs/meson.build new file mode 100644 index 000000000..1a24eb6b4 --- /dev/null +++ b/lib/nas/5gs/meson.build @@ -0,0 +1,37 @@ +# Copyright (C) 2019 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 . + +libnas_5gs_sources = files(''' + ies.c + decoder.c + encoder.c +'''.split()) + +libnas_5gs_inc = include_directories('.') + +libnas_5gs = library('ogsnas-5gs', + sources : libnas_5gs_sources, + version : libogslib_version, + c_args : '-DOGS_NAS_COMPILATION', + include_directories : libnas_5gs_inc, + dependencies : libnas_common_dep, + install : true) + +libnas_5gs_dep = declare_dependency( + link_with : libnas_5gs, + include_directories : libnas_5gs_inc, + dependencies : libnas_common_dep) diff --git a/lib/nas/5gs/message.h b/lib/nas/5gs/message.h new file mode 100644 index 000000000..e10fb4b1a --- /dev/null +++ b/lib/nas/5gs/message.h @@ -0,0 +1,1384 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 21:20:09.032866 by acetcom + * from 24501-g41.docx + ******************************************************************************/ + +#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_5GS_MESSAGE_H +#define OGS_NAS_5GS_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ +#define OGS_NAS_HEADROOM 16 + +#define OGS_NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE 0 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED 1 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED 2 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT 3 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHTERD_WITH_NEW_INTEGRITY_CONTEXT 4 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_PARTICALLY_CIPHTERD 5 + +#define OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_ESM 0x2e +#define OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_EMM 0x7e + +#define OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED 0 +#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0 + +typedef struct ogs_nas_5gmm_header_s { + uint8_t extended_protocol_discriminator; + uint8_t security_header_type; + uint8_t message_type; +} __attribute__ ((packed)) ogs_nas_5gmm_header_t; + +typedef struct ogs_nas_5gsm_header_s { + uint8_t extended_protocol_discriminator; + uint8_t pdu_session_identity; + uint8_t procedure_transaction_identity; + uint8_t message_type; +} __attribute__ ((packed)) ogs_nas_5gsm_header_t; + +typedef struct ogs_nas_security_header_s { + uint8_t extended_protocol_discriminator; + uint8_t security_header_type; + uint32_t message_authentication_code; + uint8_t sequence_number; +} __attribute__ ((packed)) ogs_nas_security_header_t; + +#define OGS_NAS_REGISTRATION_REQUEST 65 +#define OGS_NAS_REGISTRATION_ACCEPT 66 +#define OGS_NAS_REGISTRATION_COMPLETE 67 +#define OGS_NAS_REGISTRATION_REJECT 68 +#define OGS_NAS_DEREGISTRATION_REQUEST 69 +#define OGS_NAS_DEREGISTRATION_ACCEPT 70 +#define OGS_NAS_SERVICE_REQUEST 76 +#define OGS_NAS_SERVICE_REJECT 77 +#define OGS_NAS_SERVICE_ACCEPT 78 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND 84 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE 85 +#define OGS_NAS_AUTHENTICATION_REQUEST 86 +#define OGS_NAS_AUTHENTICATION_RESPONSE 87 +#define OGS_NAS_AUTHENTICATION_REJECT 88 +#define OGS_NAS_AUTHENTICATION_FAILURE 89 +#define OGS_NAS_AUTHENTICATION_RESULT 90 +#define OGS_NAS_IDENTITY_REQUEST 91 +#define OGS_NAS_IDENTITY_RESPONSE 92 +#define OGS_NAS_SECURITY_MODE_COMMAND 93 +#define OGS_NAS_SECURITY_MODE_COMPLETE 94 +#define OGS_NAS_SECURITY_MODE_REJECT 95 +#define OGS_NAS_5GMM_STATUS 100 +#define OGS_NAS_NOTIFICATION 101 +#define OGS_NAS_NOTIFICATION_RESPONSE 102 +#define OGS_NAS_UL_NAS_TRANSPORT 103 +#define OGS_NAS_DL_NAS_TRANSPORT 104 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST 193 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_ACCEPT 194 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REJECT 195 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMMAND 197 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE 198 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT 199 +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST 201 +#define OGS_NAS_PDU_SESSION_MODIFICATION_REJECT 202 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND 203 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE 204 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT 205 +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST 209 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT 210 +#define OGS_NAS_PDU_SESSION_RELEASE_COMMAND 211 +#define OGS_NAS_PDU_SESSION_RELEASE_COMPLETE 212 +#define OGS_NAS_5GSM_STATUS 214 + + +/******************************************************* + * REGISTRATION REQUEST + ******************************************************/ +#define OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<11) +#define OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_PRESENT ((uint64_t)1<<12) +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_PRESENT ((uint64_t)1<<13) +#define OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<14) +#define OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_PRESENT ((uint64_t)1<<15) +#define OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT ((uint64_t)1<<16) +#define OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_PRESENT ((uint64_t)1<<17) +#define OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_PRESENT ((uint64_t)1<<18) +#define OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_PRESENT ((uint64_t)1<<19) +#define OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT ((uint64_t)1<<20) +#define OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_PRESENT ((uint64_t)1<<21) +#define OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<22) +#define OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT ((uint64_t)1<<23) +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_PRESENT ((uint64_t)1<<24) +#define OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_PRESENT ((uint64_t)1<<25) +#define OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_PRESENT ((uint64_t)1<<26) +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_PRESENT ((uint64_t)1<<27) +#define OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_PRESENT ((uint64_t)1<<28) +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_PRESENT ((uint64_t)1<<29) +#define OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_PRESENT ((uint64_t)1<<30) +#define OGS_NAS_REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE 0xC0 +#define OGS_NAS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE 0x10 +#define OGS_NAS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE 0x2E +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_NSSAI_TYPE 0x2F +#define OGS_NAS_REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE 0x52 +#define OGS_NAS_REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_TYPE 0x17 +#define OGS_NAS_REGISTRATION_REQUEST_UPLINK_DATA_STATUS_TYPE 0x40 +#define OGS_NAS_REGISTRATION_REQUEST_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_REGISTRATION_REQUEST_MICO_INDICATION_TYPE 0xB0 +#define OGS_NAS_REGISTRATION_REQUEST_UE_STATUS_TYPE 0x2B +#define OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_GUTI_TYPE 0x77 +#define OGS_NAS_REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE 0x25 +#define OGS_NAS_REGISTRATION_REQUEST_UE_USAGE_SETTING_TYPE 0x18 +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_TYPE 0x51 +#define OGS_NAS_REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_TYPE 0x70 +#define OGS_NAS_REGISTRATION_REQUEST_LADN_INDICATION_TYPE 0x74 +#define OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE 0x80 +#define OGS_NAS_REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE 0x7B +#define OGS_NAS_REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_TYPE 0x90 +#define OGS_NAS_REGISTRATION_REQUEST_5GS_UPDATE_TYPE_TYPE 0x53 +#define OGS_NAS_REGISTRATION_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE 0x41 +#define OGS_NAS_REGISTRATION_REQUEST_SUPPORTED_CODECS_TYPE 0x42 +#define OGS_NAS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_TYPE 0x71 +#define OGS_NAS_REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE 0x60 +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_EXTENDED_DRX_PARAMETERS_TYPE 0x6E +#define OGS_NAS_REGISTRATION_REQUEST_T3324_VALUE_TYPE 0x6A +#define OGS_NAS_REGISTRATION_REQUEST_UE_RADIO_CAPABILITY_ID_TYPE 0x67 +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_MAPPED_NSSAI_TYPE 0x35 +#define OGS_NAS_REGISTRATION_REQUEST_ADDITIONAL_INFORMATION_REQUESTED_TYPE 0x48 +#define OGS_NAS_REGISTRATION_REQUEST_REQUESTED_WUS_ASSISTANCE_INFORMATION_TYPE 0x1A +#define OGS_NAS_REGISTRATION_REQUEST_N5GC_INDICATION_TYPE 0xA1 + +typedef struct ogs_nas_registration_request_s { + /* Mandatory fields */ + ogs_nas_5gs_registration_type_t registration_type; + ogs_nas_5gs_mobile_identity_t mobile_identity; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_key_set_identifier_t non_current_native_nas_key_set_identifier; + ogs_nas_5gmm_capability_t gmm_capability; + ogs_nas_ue_security_capability_t ue_security_capability; + ogs_nas_nssai_t requested_nssai; + ogs_nas_5gs_tracking_area_identity_t last_visited_registered_tai; + ogs_nas_s1_ue_network_capability_t s1_ue_network_capability; + ogs_nas_uplink_data_status_t uplink_data_status; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_mico_indication_t mico_indication; + ogs_nas_ue_status_t ue_status; + ogs_nas_5gs_mobile_identity_t additional_guti; + ogs_nas_allowed_pdu_session_status_t allowed_pdu_session_status; + ogs_nas_ue_usage_setting_t ue_usage_setting; + ogs_nas_5gs_drx_parameters_t requested_drx_parameters; + ogs_nas_eps_nas_message_container_t eps_nas_message_container; + ogs_nas_ladn_indication_t ladn_indication; + ogs_nas_payload_container_type_t payload_container_type; + ogs_nas_payload_container_t payload_container; + ogs_nas_network_slicing_indication_t network_slicing_indication; + ogs_nas_5gs_update_type_t update_type; + ogs_nas_mobile_station_classmark_2_t mobile_station_classmark_2; + ogs_nas_supported_codec_list_t supported_codecs; + ogs_nas_message_container_t nas_message_container; + ogs_nas_eps_bearer_context_status_t eps_bearer_context_status; + ogs_nas_extended_drx_parameters_t requested_extended_drx_parameters; + ogs_nas_gprs_timer_3_t t3324_value; + ogs_nas_ue_radio_capability_id_t ue_radio_capability_id; + ogs_nas_mapped_nssai_t requested_mapped_nssai; + ogs_nas_additional_information_requested_t additional_information_requested; + ogs_nas_wus_assistance_information_t requested_wus_assistance_information; + ogs_nas_n5gc_indication_t n5gc_indication; +} ogs_nas_registration_request_t; + + +/******************************************************* + * REGISTRATION ACCEPT + ******************************************************/ +#define OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_PRESENT ((uint64_t)1<<11) +#define OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_PRESENT ((uint64_t)1<<12) +#define OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_PRESENT ((uint64_t)1<<13) +#define OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_PRESENT ((uint64_t)1<<14) +#define OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_PRESENT ((uint64_t)1<<15) +#define OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_PRESENT ((uint64_t)1<<16) +#define OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT ((uint64_t)1<<17) +#define OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_PRESENT ((uint64_t)1<<18) +#define OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_PRESENT ((uint64_t)1<<19) +#define OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_PRESENT ((uint64_t)1<<20) +#define OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_PRESENT ((uint64_t)1<<21) +#define OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT ((uint64_t)1<<22) +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_PRESENT ((uint64_t)1<<23) +#define OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_PRESENT ((uint64_t)1<<24) +#define OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT ((uint64_t)1<<25) +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_PRESENT ((uint64_t)1<<26) +#define OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_PRESENT ((uint64_t)1<<27) +#define OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_PRESENT ((uint64_t)1<<28) +#define OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_PRESENT ((uint64_t)1<<29) +#define OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_PRESENT ((uint64_t)1<<30) +#define OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT ((uint64_t)1<<31) +#define OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_PRESENT ((uint64_t)1<<32) +#define OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_PRESENT ((uint64_t)1<<33) +#define OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_PRESENT ((uint64_t)1<<34) +#define OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT ((uint64_t)1<<35) +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_PRESENT ((uint64_t)1<<36) +#define OGS_NAS_REGISTRATION_ACCEPT_5G_GUTI_TYPE 0x77 +#define OGS_NAS_REGISTRATION_ACCEPT_EQUIVALENT_PLMNS_TYPE 0x4A +#define OGS_NAS_REGISTRATION_ACCEPT_TAI_LIST_TYPE 0x54 +#define OGS_NAS_REGISTRATION_ACCEPT_ALLOWED_NSSAI_TYPE 0x15 +#define OGS_NAS_REGISTRATION_ACCEPT_REJECTED_NSSAI_TYPE 0x11 +#define OGS_NAS_REGISTRATION_ACCEPT_CONFIGURED_NSSAI_TYPE 0x31 +#define OGS_NAS_REGISTRATION_ACCEPT_5GS_NETWORK_FEATURE_SUPPORT_TYPE 0x21 +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE 0x26 +#define OGS_NAS_REGISTRATION_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE 0x72 +#define OGS_NAS_REGISTRATION_ACCEPT_LADN_INFORMATION_TYPE 0x79 +#define OGS_NAS_REGISTRATION_ACCEPT_MICO_INDICATION_TYPE 0xB0 +#define OGS_NAS_REGISTRATION_ACCEPT_NETWORK_SLICING_INDICATION_TYPE 0x90 +#define OGS_NAS_REGISTRATION_ACCEPT_SERVICE_AREA_LIST_TYPE 0x27 +#define OGS_NAS_REGISTRATION_ACCEPT_T3512_VALUE_TYPE 0x5E +#define OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_DE_REGISTRATION_TIMER_VALUE_TYPE 0x5D +#define OGS_NAS_REGISTRATION_ACCEPT_T3502_VALUE_TYPE 0x16 +#define OGS_NAS_REGISTRATION_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE 0x34 +#define OGS_NAS_REGISTRATION_ACCEPT_EXTENDED_EMERGENCY_NUMBER_LIST_TYPE 0x7A +#define OGS_NAS_REGISTRATION_ACCEPT_SOR_TRANSPARENT_CONTAINER_TYPE 0x73 +#define OGS_NAS_REGISTRATION_ACCEPT_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_REGISTRATION_ACCEPT_NSSAI_INCLUSION_MODE_TYPE 0xA0 +#define OGS_NAS_REGISTRATION_ACCEPT_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE 0x76 +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_DRX_PARAMETERS_TYPE 0x51 +#define OGS_NAS_REGISTRATION_ACCEPT_NON_3GPP_NW_POLICIES_TYPE 0xD0 +#define OGS_NAS_REGISTRATION_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE 0x60 +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_EXTENDED_DRX_PARAMETERS_TYPE 0x6E +#define OGS_NAS_REGISTRATION_ACCEPT_T3447_VALUE_TYPE 0x6C +#define OGS_NAS_REGISTRATION_ACCEPT_T3448_VALUE_TYPE 0x6B +#define OGS_NAS_REGISTRATION_ACCEPT_T3324_VALUE_TYPE 0x6A +#define OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_TYPE 0x67 +#define OGS_NAS_REGISTRATION_ACCEPT_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE 0x68 +#define OGS_NAS_REGISTRATION_ACCEPT_PENDING_NSSAI_TYPE 0x39 +#define OGS_NAS_REGISTRATION_ACCEPT_CIPHERING_KEY_DATA_TYPE 0x74 +#define OGS_NAS_REGISTRATION_ACCEPT_CAG_INFORMATION_LIST_TYPE 0x75 +#define OGS_NAS_REGISTRATION_ACCEPT_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE 0x1B +#define OGS_NAS_REGISTRATION_ACCEPT_NEGOTIATED_WUS_ASSISTANCE_INFORMATION_TYPE 0x1C + +typedef struct ogs_nas_registration_accept_s { + /* Mandatory fields */ + ogs_nas_5gs_registration_result_t registration_result; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gs_mobile_identity_t guti; + ogs_nas_plmn_list_t equivalent_plmns; + ogs_nas_5gs_tracking_area_identity_list_t tai_list; + ogs_nas_nssai_t allowed_nssai; + ogs_nas_rejected_nssai_t rejected_nssai; + ogs_nas_nssai_t configured_nssai; + ogs_nas_5gs_network_feature_support_t network_feature_support; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_pdu_session_reactivation_result_t pdu_session_reactivation_result; + ogs_nas_pdu_session_reactivation_result_error_cause_t pdu_session_reactivation_result_error_cause; + ogs_nas_ladn_information_t ladn_information; + ogs_nas_mico_indication_t mico_indication; + ogs_nas_network_slicing_indication_t network_slicing_indication; + ogs_nas_service_area_list_t service_area_list; + ogs_nas_gprs_timer_3_t t3512_value; + ogs_nas_gprs_timer_2_t non_3gpp_de_registration_timer_value; + ogs_nas_gprs_timer_2_t t3502_value; + ogs_nas_emergency_number_list_t emergency_number_list; + ogs_nas_extended_emergency_number_list_t extended_emergency_number_list; + ogs_nas_sor_transparent_container_t sor_transparent_container; + ogs_nas_eap_message_t eap_message; + ogs_nas_nssai_inclusion_mode_t nssai_inclusion_mode; + ogs_nas_operator_defined_access_category_definitions_t operator_defined_access_category_definitions; + ogs_nas_5gs_drx_parameters_t negotiated_drx_parameters; + ogs_nas_non_3gpp_nw_provided_policies_t non_3gpp_nw_policies; + ogs_nas_eps_bearer_context_status_t eps_bearer_context_status; + ogs_nas_extended_drx_parameters_t negotiated_extended_drx_parameters; + ogs_nas_gprs_timer_3_t t3447_value; + ogs_nas_gprs_timer_3_t t3448_value; + ogs_nas_gprs_timer_3_t t3324_value; + ogs_nas_ue_radio_capability_id_t ue_radio_capability_id; + ogs_nas_ue_radio_capability_id_deletion_indication_t ue_radio_capability_id_deletion_indication; + ogs_nas_nssai_t pending_nssai; + ogs_nas_ciphering_key_data_t ciphering_key_data; + ogs_nas_cag_information_list_t cag_information_list; + ogs_nas_truncated_5g_s_tmsi_configuration_t truncated_s_tmsi_configuration; + ogs_nas_wus_assistance_information_t negotiated_wus_assistance_information; +} ogs_nas_registration_accept_t; + + +/******************************************************* + * REGISTRATION COMPLETE + ******************************************************/ +#define OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_REGISTRATION_COMPLETE_SOR_TRANSPARENT_CONTAINER_TYPE 0x73 + +typedef struct ogs_nas_registration_complete_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_sor_transparent_container_t sor_transparent_container; +} ogs_nas_registration_complete_t; + + +/******************************************************* + * REGISTRATION REJECT + ******************************************************/ +#define OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_REGISTRATION_REJECT_T3346_VALUE_TYPE 0x5F +#define OGS_NAS_REGISTRATION_REJECT_T3502_VALUE_TYPE 0x16 +#define OGS_NAS_REGISTRATION_REJECT_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_REGISTRATION_REJECT_REJECTED_NSSAI_TYPE 0x69 + +typedef struct ogs_nas_registration_reject_s { + /* Mandatory fields */ + ogs_nas_5gmm_cause_t gmm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_gprs_timer_2_t t3346_value; + ogs_nas_gprs_timer_2_t t3502_value; + ogs_nas_eap_message_t eap_message; + ogs_nas_rejected_nssai_t rejected_nssai; +} ogs_nas_registration_reject_t; + + +/******************************************************* + * DEREGISTRATION REQUEST FROM UE + ******************************************************/ + +typedef struct ogs_nas_deregistration_request_from_ue_s { + /* Mandatory fields */ + ogs_nas_de_registration_type_t de_registration_type; + ogs_nas_5gs_mobile_identity_t mobile_identity; +} ogs_nas_deregistration_request_from_ue_t; + + +/******************************************************* + * DEREGISTRATION REQUEST TO UE + ******************************************************/ +#define OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_DEREGISTRATION_REQUEST_5GMM_CAUSE_TYPE 0x58 +#define OGS_NAS_DEREGISTRATION_REQUEST_T3346_VALUE_TYPE 0x5F +#define OGS_NAS_DEREGISTRATION_REQUEST_REJECTED_NSSAI_TYPE 0x6D + +typedef struct ogs_nas_deregistration_request_to_ue_s { + /* Mandatory fields */ + ogs_nas_de_registration_type_t de_registration_type; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gmm_cause_t gmm_cause; + ogs_nas_gprs_timer_2_t t3346_value; + ogs_nas_rejected_nssai_t rejected_nssai; +} ogs_nas_deregistration_request_to_ue_t; + + +/******************************************************* + * SERVICE REQUEST + ******************************************************/ +#define OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_SERVICE_REQUEST_UPLINK_DATA_STATUS_TYPE 0x40 +#define OGS_NAS_SERVICE_REQUEST_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_SERVICE_REQUEST_ALLOWED_PDU_SESSION_STATUS_TYPE 0x25 +#define OGS_NAS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_TYPE 0x71 + +typedef struct ogs_nas_service_request_s { + /* Mandatory fields */ + ogs_nas_key_set_identifier_t ngksi; + ogs_nas_5gs_mobile_identity_t s_tmsi; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_uplink_data_status_t uplink_data_status; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_allowed_pdu_session_status_t allowed_pdu_session_status; + ogs_nas_message_container_t nas_message_container; +} ogs_nas_service_request_t; + + +/******************************************************* + * SERVICE REJECT + ******************************************************/ +#define OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_SERVICE_REJECT_T3448_VALUE_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_SERVICE_REJECT_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE 0x5F +#define OGS_NAS_SERVICE_REJECT_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_SERVICE_REJECT_T3448_VALUE_TYPE 0x6B + +typedef struct ogs_nas_service_reject_s { + /* Mandatory fields */ + ogs_nas_5gmm_cause_t gmm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_gprs_timer_2_t t3346_value; + ogs_nas_eap_message_t eap_message; + ogs_nas_gprs_timer_3_t t3448_value; +} ogs_nas_service_reject_t; + + +/******************************************************* + * SERVICE ACCEPT + ******************************************************/ +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_TYPE 0x26 +#define OGS_NAS_SERVICE_ACCEPT_PDU_SESSION_REACTIVATION_RESULT_ERROR_CAUSE_TYPE 0x72 +#define OGS_NAS_SERVICE_ACCEPT_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_SERVICE_ACCEPT_T3448_VALUE_TYPE 0x6B + +typedef struct ogs_nas_service_accept_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_pdu_session_reactivation_result_t pdu_session_reactivation_result; + ogs_nas_pdu_session_reactivation_result_error_cause_t pdu_session_reactivation_result_error_cause; + ogs_nas_eap_message_t eap_message; + ogs_nas_gprs_timer_3_t t3448_value; +} ogs_nas_service_accept_t; + + +/******************************************************* + * CONFIGURATION UPDATE COMMAND + ******************************************************/ +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_PRESENT ((uint64_t)1<<11) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_PRESENT ((uint64_t)1<<12) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_PRESENT ((uint64_t)1<<13) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_PRESENT ((uint64_t)1<<14) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_PRESENT ((uint64_t)1<<15) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_PRESENT ((uint64_t)1<<16) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_PRESENT ((uint64_t)1<<17) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_PRESENT ((uint64_t)1<<18) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_PRESENT ((uint64_t)1<<19) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_PRESENT ((uint64_t)1<<20) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_PRESENT ((uint64_t)1<<21) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_PRESENT ((uint64_t)1<<22) +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURATION_UPDATE_INDICATION_TYPE 0xD0 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_TYPE 0x77 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TAI_LIST_TYPE 0x54 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_ALLOWED_NSSAI_TYPE 0x15 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SERVICE_AREA_LIST_TYPE 0x27 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_FULL_NAME_FOR_NETWORK_TYPE 0x43 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SHORT_NAME_FOR_NETWORK_TYPE 0x45 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LOCAL_TIME_ZONE_TYPE 0x46 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE 0x47 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_DAYLIGHT_SAVING_TIME_TYPE 0x49 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_LADN_INFORMATION_TYPE 0x79 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_MICO_INDICATION_TYPE 0xB0 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_NETWORK_SLICING_INDICATION_TYPE 0x90 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CONFIGURED_NSSAI_TYPE 0x31 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_REJECTED_NSSAI_TYPE 0x11 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_OPERATOR_DEFINED_ACCESS_CATEGORY_DEFINITIONS_TYPE 0x76 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_SMS_INDICATION_TYPE 0xF0 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_T3447_VALUE_TYPE 0x6C +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_CAG_INFORMATION_LIST_TYPE 0x75 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_TYPE 0x67 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_UE_RADIO_CAPABILITY_ID_DELETION_INDICATION_TYPE 0x68 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_5GS_REGISTRATION_RESULT_TYPE 0x44 +#define OGS_NAS_CONFIGURATION_UPDATE_COMMAND_TRUNCATED_5G_S_TMSI_CONFIGURATION_TYPE 0x1B + +typedef struct ogs_nas_configuration_update_command_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_configuration_update_indication_t configuration_update_indication; + ogs_nas_5gs_mobile_identity_t guti; + ogs_nas_5gs_tracking_area_identity_list_t tai_list; + ogs_nas_nssai_t allowed_nssai; + ogs_nas_service_area_list_t service_area_list; + ogs_nas_network_name_t full_name_for_network; + ogs_nas_network_name_t short_name_for_network; + ogs_nas_time_zone_t local_time_zone; + ogs_nas_time_zone_and_time_t universal_time_and_local_time_zone; + ogs_nas_daylight_saving_time_t network_daylight_saving_time; + ogs_nas_ladn_information_t ladn_information; + ogs_nas_mico_indication_t mico_indication; + ogs_nas_network_slicing_indication_t network_slicing_indication; + ogs_nas_nssai_t configured_nssai; + ogs_nas_rejected_nssai_t rejected_nssai; + ogs_nas_operator_defined_access_category_definitions_t operator_defined_access_category_definitions; + ogs_nas_sms_indication_t sms_indication; + ogs_nas_gprs_timer_3_t t3447_value; + ogs_nas_cag_information_list_t cag_information_list; + ogs_nas_ue_radio_capability_id_t ue_radio_capability_id; + ogs_nas_ue_radio_capability_id_deletion_indication_t ue_radio_capability_id_deletion_indication; + ogs_nas_5gs_registration_result_t registration_result; + ogs_nas_truncated_5g_s_tmsi_configuration_t truncated_s_tmsi_configuration; +} ogs_nas_configuration_update_command_t; + + +/******************************************************* + * CONFIGURATION UPDATE COMPLETE + ******************************************************/ +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_CIOT_SMALL_DATA_CONTAINER_TYPE 0x6F +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE_TYPE 0x80 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PAYLOAD_CONTAINER_TYPE 0x7B +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_RELEASE_ASSISTANCE_INDICATION_TYPE 0xF0 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_UPLINK_DATA_STATUS_TYPE 0x40 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE 0x71 +#define OGS_NAS_CONFIGURATION_UPDATE_COMPLETE_ADDITIONAL_INFORMATION_TYPE 0x24 + +typedef struct ogs_nas_configuration_update_complete_s { + /* Mandatory fields */ + ogs_nas_control_plane_service_type_t control_plane_service_type; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_ciot_small_data_container_t ciot_small_data_container; + ogs_nas_payload_container_type_t payload_container_type; + ogs_nas_payload_container_t payload_container; + ogs_nas_pdu_session_identity_2_t pdu_session_id; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_release_assistance_indication_t release_assistance_indication; + ogs_nas_uplink_data_status_t uplink_data_status; + ogs_nas_message_container_t nas_message_container; + ogs_nas_additional_information_t additional_information; +} ogs_nas_configuration_update_complete_t; + + +/******************************************************* + * AUTHENTICATION REQUEST + ******************************************************/ +#define OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_RAND_TYPE 0x21 +#define OGS_NAS_AUTHENTICATION_REQUEST_AUTHENTICATION_PARAMETER_AUTN_TYPE 0x20 +#define OGS_NAS_AUTHENTICATION_REQUEST_EAP_MESSAGE_TYPE 0x78 + +typedef struct ogs_nas_authentication_request_s { + /* Mandatory fields */ + ogs_nas_key_set_identifier_t ngksi; + ogs_nas_abba_t abba; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_authentication_parameter_rand_t authentication_parameter_rand; + ogs_nas_authentication_parameter_autn_t authentication_parameter_autn; + ogs_nas_eap_message_t eap_message; +} ogs_nas_authentication_request_t; + + +/******************************************************* + * AUTHENTICATION RESPONSE + ******************************************************/ +#define OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_AUTHENTICATION_RESPONSE_AUTHENTICATION_RESPONSE_PARAMETER_TYPE 0x2D +#define OGS_NAS_AUTHENTICATION_RESPONSE_EAP_MESSAGE_TYPE 0x78 + +typedef struct ogs_nas_authentication_response_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_authentication_response_parameter_t authentication_response_parameter; + ogs_nas_eap_message_t eap_message; +} ogs_nas_authentication_response_t; + + +/******************************************************* + * AUTHENTICATION REJECT + ******************************************************/ +#define OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_AUTHENTICATION_REJECT_EAP_MESSAGE_TYPE 0x78 + +typedef struct ogs_nas_authentication_reject_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_eap_message_t eap_message; +} ogs_nas_authentication_reject_t; + + +/******************************************************* + * AUTHENTICATION FAILURE + ******************************************************/ +#define OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE 0x30 + +typedef struct ogs_nas_authentication_failure_s { + /* Mandatory fields */ + ogs_nas_5gmm_cause_t gmm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_authentication_failure_parameter_t authentication_failure_parameter; +} ogs_nas_authentication_failure_t; + + +/******************************************************* + * AUTHENTICATION RESULT + ******************************************************/ +#define OGS_NAS_AUTHENTICATION_RESULT_ABBA_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_AUTHENTICATION_RESULT_ABBA_TYPE 0x38 + +typedef struct ogs_nas_authentication_result_s { + /* Mandatory fields */ + ogs_nas_key_set_identifier_t ngksi; + ogs_nas_eap_message_t eap_message; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_abba_t abba; +} ogs_nas_authentication_result_t; + + +/******************************************************* + * IDENTITY REQUEST + ******************************************************/ + +typedef struct ogs_nas_identity_request_s { + /* Mandatory fields */ + ogs_nas_5gs_identity_type_t identity_type; +} ogs_nas_identity_request_t; + + +/******************************************************* + * IDENTITY RESPONSE + ******************************************************/ + +typedef struct ogs_nas_identity_response_s { + /* Mandatory fields */ + ogs_nas_5gs_mobile_identity_t mobile_identity; +} ogs_nas_identity_response_t; + + +/******************************************************* + * SECURITY MODE COMMAND + ******************************************************/ +#define OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_SECURITY_MODE_COMMAND_ABBA_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE 0xE0 +#define OGS_NAS_SECURITY_MODE_COMMAND_SELECTED_EPS_NAS_SECURITY_ALGORITHMS_TYPE 0x57 +#define OGS_NAS_SECURITY_MODE_COMMAND_ADDITIONAL_5G_SECURITY_INFORMATION_TYPE 0x36 +#define OGS_NAS_SECURITY_MODE_COMMAND_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_SECURITY_MODE_COMMAND_ABBA_TYPE 0x38 +#define OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_S1_UE_SECURITY_CAPABILITIES_TYPE 0x19 + +typedef struct ogs_nas_security_mode_command_s { + /* Mandatory fields */ + ogs_nas_security_algorithms_t selected_nas_security_algorithms; + ogs_nas_key_set_identifier_t ngksi; + ogs_nas_ue_security_capability_t replayed_ue_security_capabilities; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_imeisv_request_t imeisv_request; + ogs_nas_eps_nas_security_algorithms_t selected_eps_nas_security_algorithms; + ogs_nas_additional_5g_security_information_t additional_security_information; + ogs_nas_eap_message_t eap_message; + ogs_nas_abba_t abba; + ogs_nas_s1_ue_security_capability_t replayed_s1_ue_security_capabilities; +} ogs_nas_security_mode_command_t; + + +/******************************************************* + * SECURITY MODE COMPLETE + ******************************************************/ +#define OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE 0x77 +#define OGS_NAS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_TYPE 0x71 +#define OGS_NAS_SECURITY_MODE_COMPLETE_NON_IMEISV_PEI_TYPE 0x78 + +typedef struct ogs_nas_security_mode_complete_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gs_mobile_identity_t imeisv; + ogs_nas_message_container_t nas_message_container; + ogs_nas_5gs_mobile_identity_t non_imeisv_pei; +} ogs_nas_security_mode_complete_t; + + +/******************************************************* + * SECURITY MODE REJECT + ******************************************************/ + +typedef struct ogs_nas_security_mode_reject_s { + /* Mandatory fields */ + ogs_nas_5gmm_cause_t gmm_cause; +} ogs_nas_security_mode_reject_t; + + +/******************************************************* + * 5GMM STATUS + ******************************************************/ + +typedef struct ogs_nas_5gmm_status_s { + /* Mandatory fields */ + ogs_nas_5gmm_cause_t gmm_cause; +} ogs_nas_5gmm_status_t; + + +/******************************************************* + * NOTIFICATION + ******************************************************/ + +typedef struct ogs_nas_notification_s { + /* Mandatory fields */ + ogs_nas_access_type_t access_type; +} ogs_nas_notification_t; + + +/******************************************************* + * NOTIFICATION RESPONSE + ******************************************************/ +#define OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_NOTIFICATION_RESPONSE_PDU_SESSION_STATUS_TYPE 0x50 + +typedef struct ogs_nas_notification_response_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_pdu_session_status_t pdu_session_status; +} ogs_nas_notification_response_t; + + +/******************************************************* + * UL NAS TRANSPORT + ******************************************************/ +#define OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_UL_NAS_TRANSPORT_DNN_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_UL_NAS_TRANSPORT_OLD_PDU_SESSION_ID_TYPE 0x59 +#define OGS_NAS_UL_NAS_TRANSPORT_REQUEST_TYPE_TYPE 0x8 +#define OGS_NAS_UL_NAS_TRANSPORT_S_NSSAI_TYPE 0x22 +#define OGS_NAS_UL_NAS_TRANSPORT_DNN_TYPE 0x25 +#define OGS_NAS_UL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE 0x24 +#define OGS_NAS_UL_NAS_TRANSPORT_MA_PDU_SESSION_INFORMATION_TYPE 0xA0 +#define OGS_NAS_UL_NAS_TRANSPORT_RELEASE_ASSISTANCE_INDICATION_TYPE 0xF0 + +typedef struct ogs_nas_ul_nas_transport_s { + /* Mandatory fields */ + ogs_nas_payload_container_type_t payload_container_type; + ogs_nas_payload_container_t payload_container; + ogs_nas_pdu_session_identity_2_t pdu_session_id; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_pdu_session_identity_2_t old_pdu_session_id; + ogs_nas_request_type_t request_type; + ogs_nas_s_nssai_t s_nssai; + ogs_nas_dnn_t dnn; + ogs_nas_additional_information_t additional_information; + ogs_nas_ma_pdu_session_information_t ma_pdu_session_information; + ogs_nas_release_assistance_indication_t release_assistance_indication; +} ogs_nas_ul_nas_transport_t; + + +/******************************************************* + * DL NAS TRANSPORT + ******************************************************/ +#define OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_DL_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE 0x24 +#define OGS_NAS_DL_NAS_TRANSPORT_5GMM_CAUSE_TYPE 0x58 +#define OGS_NAS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_TYPE 0x37 + +typedef struct ogs_nas_dl_nas_transport_s { + /* Mandatory fields */ + ogs_nas_payload_container_type_t payload_container_type; + ogs_nas_payload_container_t payload_container; + ogs_nas_pdu_session_identity_2_t pdu_session_id; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_additional_information_t additional_information; + ogs_nas_5gmm_cause_t gmm_cause; + ogs_nas_gprs_timer_3_t back_off_timer_value; +} ogs_nas_dl_nas_transport_t; + + +/******************************************************* + * PDU SESSION ESTABLISHMENT REQUEST + ******************************************************/ +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_CIOT_SMALL_DATA_CONTAINER_TYPE 0x6F +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE_TYPE 0x80 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PAYLOAD_CONTAINER_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_PDU_SESSION_STATUS_TYPE 0x50 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_RELEASE_ASSISTANCE_INDICATION_TYPE 0xF0 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_UPLINK_DATA_STATUS_TYPE 0x40 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_NAS_MESSAGE_CONTAINER_TYPE 0x71 +#define OGS_NAS_PDU_SESSION_ESTABLISHMENT_REQUEST_ADDITIONAL_INFORMATION_TYPE 0x24 + +typedef struct ogs_nas_pdu_session_establishment_request_s { + /* Mandatory fields */ + ogs_nas_control_plane_service_type_t control_plane_service_type; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_ciot_small_data_container_t ciot_small_data_container; + ogs_nas_payload_container_type_t payload_container_type; + ogs_nas_payload_container_t payload_container; + ogs_nas_pdu_session_identity_2_t pdu_session_id; + ogs_nas_pdu_session_status_t pdu_session_status; + ogs_nas_release_assistance_indication_t release_assistance_indication; + ogs_nas_uplink_data_status_t uplink_data_status; + ogs_nas_message_container_t nas_message_container; + ogs_nas_additional_information_t additional_information; +} ogs_nas_pdu_session_establishment_request_t; + + +/******************************************************* + * PDU SESSION ESTABLISHMENT ACCEPT + ******************************************************/ + +typedef struct ogs_nas_pdu_session_establishment_accept_s { + /* Mandatory fields */ + ogs_nas_s_nssai_t s_nssai; + ogs_nas_eap_message_t eap_message; +} ogs_nas_pdu_session_establishment_accept_t; + + +/******************************************************* + * PDU SESSION ESTABLISHMENT REJECT + ******************************************************/ + +typedef struct ogs_nas_pdu_session_establishment_reject_s { + /* Mandatory fields */ + ogs_nas_s_nssai_t s_nssai; + ogs_nas_eap_message_t eap_message; +} ogs_nas_pdu_session_establishment_reject_t; + + +/******************************************************* + * PDU SESSION AUTHENTICATION COMMAND + ******************************************************/ + +typedef struct ogs_nas_pdu_session_authentication_command_s { + /* Mandatory fields */ + ogs_nas_s_nssai_t s_nssai; + ogs_nas_eap_message_t eap_message; +} ogs_nas_pdu_session_authentication_command_t; + + +/******************************************************* + * PDU SESSION AUTHENTICATION COMPLETE + ******************************************************/ +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PDU_SESSION_TYPE_TYPE 0x90 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SSC_MODE_TYPE 0xA0 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_5GSM_CAPABILITY_TYPE 0x28 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE 0x55 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE 0xB0 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_SM_PDU_DN_REQUEST_CONTAINER_TYPE 0x39 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_HEADER_COMPRESSION_CONFIGURATION_TYPE 0x66 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_DS_TT_ETHERNET_PORT_MAC_ADDRESS_TYPE 0x6E +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_UE_DS_TT_RESIDENCE_TIME_TYPE 0x6F +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_COMPLETE_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE 0x7C + +typedef struct ogs_nas_pdu_session_authentication_complete_s { + /* Mandatory fields */ + ogs_nas_integrity_protection_maximum_data_rate_t integrity_protection_maximum_data_rate; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_pdu_session_type_t pdu_session_type; + ogs_nas_ssc_mode_t ssc_mode; + ogs_nas_5gsm_capability_t gsm_capability; + ogs_nas_maximum_number_of_supported_packet_filters_t maximum_number_of_supported_packet_filters; + ogs_nas_always_on_pdu_session_requested_t always_on_pdu_session_requested; + ogs_nas_sm_pdu_dn_request_container_t sm_pdu_dn_request_container; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_header_compression_configuration_t header_compression_configuration; + ogs_nas_ds_tt_ethernet_port_mac_address_t ds_tt_ethernet_port_mac_address; + ogs_nas_ue_ds_tt_residence_time_t ue_ds_tt_residence_time; + ogs_nas_port_management_information_container_t port_management_information_container; +} ogs_nas_pdu_session_authentication_complete_t; + + +/******************************************************* + * PDU SESSION AUTHENTICATION RESULT + ******************************************************/ +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_PRESENT ((uint64_t)1<<11) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_PRESENT ((uint64_t)1<<12) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_PRESENT ((uint64_t)1<<13) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_PRESENT ((uint64_t)1<<14) +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_CAUSE_TYPE 0x59 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_PDU_ADDRESS_TYPE 0x29 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_RQ_TIMER_VALUE_TYPE 0x56 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_S_NSSAI_TYPE 0x22 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE 0x80 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_MAPPED_EPS_BEARER_CONTEXTS_TYPE 0x75 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE 0x79 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_DNN_TYPE 0x25 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_5GSM_NETWORK_FEATURE_SUPPORT_TYPE 0x17 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_SERVING_PLMN_RATE_CONTROL_TYPE 0x18 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_ATSSS_CONTAINER_TYPE 0x77 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_CONTROL_PLANE_ONLY_INDICATION_TYPE 0xC0 +#define OGS_NAS_PDU_SESSION_AUTHENTICATION_RESULT_HEADER_COMPRESSION_CONFIGURATION_TYPE 0x66 + +typedef struct ogs_nas_pdu_session_authentication_result_s { + /* Mandatory fields */ + ogs_nas_pdu_session_type_t selected_pdu_session_type; + ogs_nas_qos_rules_t authorized_qos_rules; + ogs_nas_session_ambr_t session_ambr; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gsm_cause_t gsm_cause; + ogs_nas_pdu_address_t pdu_address; + ogs_nas_gprs_timer_t rq_timer_value; + ogs_nas_s_nssai_t s_nssai; + ogs_nas_always_on_pdu_session_indication_t always_on_pdu_session_indication; + ogs_nas_mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + ogs_nas_eap_message_t eap_message; + ogs_nas_qos_flow_descriptions_t authorized_qos_flow_descriptions; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_dnn_t dnn; + ogs_nas_5gsm_network_feature_support_t gsm_network_feature_support; + ogs_nas_serving_plmn_rate_control_t serving_plmn_rate_control; + ogs_nas_atsss_container_t atsss_container; + ogs_nas_control_plane_only_indication_t control_plane_only_indication; + ogs_nas_header_compression_configuration_t header_compression_configuration; +} ogs_nas_pdu_session_authentication_result_t; + + +/******************************************************* + * PDU SESSION MODIFICATION REQUEST + ******************************************************/ +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_BACK_OFF_TIMER_VALUE_TYPE 0x37 +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_ALLOWED_SSC_MODE_TYPE 0xF0 +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_RE_ATTEMPT_INDICATOR_TYPE 0x1D +#define OGS_NAS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE 0x61 + +typedef struct ogs_nas_pdu_session_modification_request_s { + /* Mandatory fields */ + ogs_nas_5gsm_cause_t gsm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_gprs_timer_3_t back_off_timer_value; + ogs_nas_allowed_ssc_mode_t allowed_ssc_mode; + ogs_nas_eap_message_t eap_message; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_re_attempt_indicator_t re_attempt_indicator; + ogs_nas_5gsm_congestion_re_attempt_indicator_t gsm_congestion_re_attempt_indicator; +} ogs_nas_pdu_session_modification_request_t; + + +/******************************************************* + * PDU SESSION MODIFICATION REJECT + ******************************************************/ +#define OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B + +typedef struct ogs_nas_pdu_session_modification_reject_s { + /* Mandatory fields */ + ogs_nas_eap_message_t eap_message; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; +} ogs_nas_pdu_session_modification_reject_t; + + +/******************************************************* + * PDU SESSION MODIFICATION COMMAND + ******************************************************/ +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B + +typedef struct ogs_nas_pdu_session_modification_command_s { + /* Mandatory fields */ + ogs_nas_eap_message_t eap_message; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; +} ogs_nas_pdu_session_modification_command_t; + + +/******************************************************* + * PDU SESSION MODIFICATION COMPLETE + ******************************************************/ +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EAP_MESSAGE_TYPE 0x78 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B + +typedef struct ogs_nas_pdu_session_modification_complete_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_eap_message_t eap_message; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; +} ogs_nas_pdu_session_modification_complete_t; + + +/******************************************************* + * PDU SESSION MODIFICATION COMMAND REJECT + ******************************************************/ +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAPABILITY_TYPE 0x28 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_5GSM_CAUSE_TYPE 0x59 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAXIMUM_NUMBER_OF_SUPPORTED_PACKET_FILTERS_TYPE 0x55 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_ALWAYS_ON_PDU_SESSION_REQUESTED_TYPE 0xB0 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_INTEGRITY_PROTECTION_MAXIMUM_DATA_RATE_TYPE 0x13 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_RULES_TYPE 0x7A +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_REQUESTED_QOS_FLOW_DESCRIPTIONS_TYPE 0x79 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE 0x75 +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE 0x7C +#define OGS_NAS_PDU_SESSION_MODIFICATION_COMMAND_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE 0x66 + +typedef struct ogs_nas_pdu_session_modification_command_reject_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gsm_capability_t gsm_capability; + ogs_nas_5gsm_cause_t gsm_cause; + ogs_nas_maximum_number_of_supported_packet_filters_t maximum_number_of_supported_packet_filters; + ogs_nas_always_on_pdu_session_requested_t always_on_pdu_session_requested; + ogs_nas_integrity_protection_maximum_data_rate_t integrity_protection_maximum_data_rate; + ogs_nas_qos_rules_t requested_qos_rules; + ogs_nas_qos_flow_descriptions_t requested_qos_flow_descriptions; + ogs_nas_mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_port_management_information_container_t port_management_information_container; + ogs_nas_header_compression_configuration_t header_compression_configuration; +} ogs_nas_pdu_session_modification_command_reject_t; + + +/******************************************************* + * PDU SESSION RELEASE REQUEST + ******************************************************/ +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_BACK_OFF_TIMER_VALUE_TYPE 0x37 +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_RE_ATTEMPT_INDICATOR_TYPE 0x1D +#define OGS_NAS_PDU_SESSION_RELEASE_REQUEST_5GSM_CONGESTION_RE_ATTEMPT_INDICATOR_TYPE 0x61 + +typedef struct ogs_nas_pdu_session_release_request_s { + /* Mandatory fields */ + ogs_nas_5gsm_cause_t gsm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_gprs_timer_3_t back_off_timer_value; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_re_attempt_indicator_t re_attempt_indicator; + ogs_nas_5gsm_congestion_re_attempt_indicator_t gsm_congestion_re_attempt_indicator; +} ogs_nas_pdu_session_release_request_t; + + +/******************************************************* + * PDU SESSION RELEASE REJECT + ******************************************************/ +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_PRESENT ((uint64_t)1<<2) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_PRESENT ((uint64_t)1<<3) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_PRESENT ((uint64_t)1<<4) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_PRESENT ((uint64_t)1<<5) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT ((uint64_t)1<<6) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<7) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_PRESENT ((uint64_t)1<<8) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_PRESENT ((uint64_t)1<<9) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT ((uint64_t)1<<10) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_PRESENT ((uint64_t)1<<11) +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_5GSM_CAUSE_TYPE 0x59 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_SESSION_AMBR_TYPE 0x2A +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_RQ_TIMER_VALUE_TYPE 0x56 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_ALWAYS_ON_PDU_SESSION_INDICATION_TYPE 0x80 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_RULES_TYPE 0x7A +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_MAPPED_EPS_BEARER_CONTEXTS_TYPE 0x75 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_TYPE 0x79 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_ATSSS_CONTAINER_TYPE 0x77 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_HEADER_COMPRESSION_CONFIGURATION_TYPE 0x66 +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE 0x7C +#define OGS_NAS_PDU_SESSION_RELEASE_REJECT_SERVING_PLMN_RATE_CONTROL_TYPE 0x1E + +typedef struct ogs_nas_pdu_session_release_reject_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gsm_cause_t gsm_cause; + ogs_nas_session_ambr_t session_ambr; + ogs_nas_gprs_timer_t rq_timer_value; + ogs_nas_always_on_pdu_session_indication_t always_on_pdu_session_indication; + ogs_nas_qos_rules_t authorized_qos_rules; + ogs_nas_mapped_eps_bearer_contexts_t mapped_eps_bearer_contexts; + ogs_nas_qos_flow_descriptions_t authorized_qos_flow_descriptions; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_atsss_container_t atsss_container; + ogs_nas_header_compression_configuration_t header_compression_configuration; + ogs_nas_port_management_information_container_t port_management_information_container; + ogs_nas_serving_plmn_rate_control_t serving_plmn_rate_control; +} ogs_nas_pdu_session_release_reject_t; + + +/******************************************************* + * PDU SESSION RELEASE COMMAND + ******************************************************/ +#define OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_PDU_SESSION_RELEASE_COMMAND_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B +#define OGS_NAS_PDU_SESSION_RELEASE_COMMAND_PORT_MANAGEMENT_INFORMATION_CONTAINER_TYPE 0x7C + +typedef struct ogs_nas_pdu_session_release_command_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; + ogs_nas_port_management_information_container_t port_management_information_container; +} ogs_nas_pdu_session_release_command_t; + + +/******************************************************* + * PDU SESSION RELEASE COMPLETE + ******************************************************/ +#define OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_PDU_SESSION_RELEASE_COMPLETE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B + +typedef struct ogs_nas_pdu_session_release_complete_s { + /* Mandatory fields */ + ogs_nas_5gsm_cause_t gsm_cause; + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; +} ogs_nas_pdu_session_release_complete_t; + + +/******************************************************* + * 5GSM STATUS + ******************************************************/ +#define OGS_NAS_5GSM_STATUS_5GSM_CAUSE_PRESENT ((uint64_t)1<<0) +#define OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT ((uint64_t)1<<1) +#define OGS_NAS_5GSM_STATUS_5GSM_CAUSE_TYPE 0x59 +#define OGS_NAS_5GSM_STATUS_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE 0x7B + +typedef struct ogs_nas_5gsm_status_s { + + /* Optional fields */ + uint64_t presencemask; + ogs_nas_5gsm_cause_t gsm_cause; + ogs_nas_extended_protocol_configuration_options_t extended_protocol_configuration_options; +} ogs_nas_5gsm_status_t; + + +typedef struct ogs_nas_5gmm_message_s { + ogs_nas_5gmm_header_t h; + union { + ogs_nas_registration_request_t registration_request; + ogs_nas_registration_accept_t registration_accept; + ogs_nas_registration_complete_t registration_complete; + ogs_nas_registration_reject_t registration_reject; + ogs_nas_deregistration_request_from_ue_t deregistration_request_from_ue; + ogs_nas_deregistration_request_to_ue_t deregistration_request_to_ue; + ogs_nas_service_request_t service_request; + ogs_nas_service_reject_t service_reject; + ogs_nas_service_accept_t service_accept; + ogs_nas_configuration_update_command_t configuration_update_command; + ogs_nas_configuration_update_complete_t configuration_update_complete; + ogs_nas_authentication_request_t authentication_request; + ogs_nas_authentication_response_t authentication_response; + ogs_nas_authentication_reject_t authentication_reject; + ogs_nas_authentication_failure_t authentication_failure; + ogs_nas_authentication_result_t authentication_result; + ogs_nas_identity_request_t identity_request; + ogs_nas_identity_response_t identity_response; + ogs_nas_security_mode_command_t security_mode_command; + ogs_nas_security_mode_complete_t security_mode_complete; + ogs_nas_security_mode_reject_t security_mode_reject; + ogs_nas_5gmm_status_t gmm_status; + ogs_nas_notification_t notification; + ogs_nas_notification_response_t notification_response; + ogs_nas_ul_nas_transport_t ul_nas_transport; + ogs_nas_dl_nas_transport_t dl_nas_transport; + }; +} ogs_nas_5gmm_message_t; + +typedef struct ogs_nas_5gsm_message_s { + ogs_nas_5gsm_header_t h; + union { + ogs_nas_pdu_session_establishment_request_t pdu_session_establishment_request; + ogs_nas_pdu_session_establishment_accept_t pdu_session_establishment_accept; + ogs_nas_pdu_session_establishment_reject_t pdu_session_establishment_reject; + ogs_nas_pdu_session_authentication_command_t pdu_session_authentication_command; + ogs_nas_pdu_session_authentication_complete_t pdu_session_authentication_complete; + ogs_nas_pdu_session_authentication_result_t pdu_session_authentication_result; + ogs_nas_pdu_session_modification_request_t pdu_session_modification_request; + ogs_nas_pdu_session_modification_reject_t pdu_session_modification_reject; + ogs_nas_pdu_session_modification_command_t pdu_session_modification_command; + ogs_nas_pdu_session_modification_complete_t pdu_session_modification_complete; + ogs_nas_pdu_session_modification_command_reject_t pdu_session_modification_command_reject; + ogs_nas_pdu_session_release_request_t pdu_session_release_request; + ogs_nas_pdu_session_release_reject_t pdu_session_release_reject; + ogs_nas_pdu_session_release_command_t pdu_session_release_command; + ogs_nas_pdu_session_release_complete_t pdu_session_release_complete; + ogs_nas_5gsm_status_t gsm_status; + }; +} ogs_nas_5gsm_message_t; + +typedef struct ogs_nas_message_s { + ogs_nas_security_header_t h; + union { + ogs_nas_5gmm_message_t gmm; + ogs_nas_5gsm_message_t gsm; + }; +} ogs_nas_message_t; + +ogs_pkbuf_t *ogs_nas_5gmm_encode(ogs_nas_message_t *message); +ogs_pkbuf_t *ogs_nas_5gsm_encode(ogs_nas_message_t *message); +int ogs_nas_5gmm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_5gsm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_MESSAGE_H */ diff --git a/lib/nas/5gs/ogs-nas-5gs.h b/lib/nas/5gs/ogs-nas-5gs.h new file mode 100644 index 000000000..ecc6b1bab --- /dev/null +++ b/lib/nas/5gs/ogs-nas-5gs.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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 . + */ + +#ifndef OGS_NAS_5GS_H +#define OGS_NAS_5GS_H + +#include "ogs-nas-common.h" + +#define OGS_NAS_INSIDE + +#include "nas/5gs/types.h" +#include "nas/5gs/ies.h" +#include "nas/5gs/message.h" + +#undef OGS_NAS_INSIDE + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_H */ diff --git a/lib/nas/5gs/support/24501-g41.docx b/lib/nas/5gs/support/24501-g41.docx new file mode 100644 index 0000000000000000000000000000000000000000..e02a5159c316dc7e13e7531f17e8f7a8e56525cd GIT binary patch literal 460032 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∈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

k? zxXLIdXX2sKuFRKusd;s=os+^ZQnU!b^($ZnA;t^-*+7`AQzeVo2{=u4zqIh}t+1@% zw*mV{Z`L}(|{B6d-ByK_Lr_9>&s0PjRmu7{)JFz*-a|IO#QK^2_L0(!jXFKYm+59D3aeJ4d#HtX0I(vs|V$a;J1V zKO&>q1)4OsV2x4Y)O0z@9ff&u2_)G%6!_!Dnj!jww739Ve$I=iZ1jidN}OUsd2Y_= zUvYHnI#O#|UA)M0JX%cGoHxuwZ~%2&u`cq-rw zH~}JMIsl}FT>(H^*pN!~2yKg2I3WhyT2s0zjLmSckD8jI(Eh+fVU&i5y`>GD^aTW* zbpGPo=I7VK6(P|;+XqntsX{CbZYTzobCODcs7S4Hp9&bz;#N?@l5(%DwjCudwH8$v z&CPREZm0H`>^y*zK(A3l9NU&n>;DpC7bZ;C)JhkjEjrJZQ8>7yEHdZ+a)XP0Pg$S0 zwT((+ak08HnC7pqRzaTDx55lxhuSx|k&NTxQpQuMwp6qKQlJkigr zs`c@MGumoe)r@=6+9v<%COFoY^?3n zOZo1ulSy1;s8fDGq{51H*Y^&_Xv>RsvVlQ14uE0JVf+JQY@@)5%BaKd+JI(k9C!y~ z=8*u^^Q+QAcfq6%a!}G;L8^scedTI=n)D3v$*%0Ob(@VpYZ&T zAL#&J$oFq!(-gsE-W_$DldS-Ezv=(TaQKD`?LKE$fz~HR2Gm*@arp)TRS&QTq6@&D zJ)#h_#gyP>w=l+$v$q@-s2M_}12b%Cy(!?1CtuNxACYd78M2Tc{0$-_`t2QdRs% ze6Ne&v_8#?rb$<#OM-!DxioK^$#}_l2Sr&;JHVsLBbvv)nBqbo2O_pgaHx!+Y>g5L z?jJ)U9BLwO)8)WwV8tL{O+s=q(Q>HrCYb97jp1LJF{tGJx&HwiGwP6+yci}?svg%2 zeAy6?Gl1{?vjjc!=DBtiehqzVAMz;+ggIC;>6X$NKN!K;|9eb?9i5*P>Qv->c@{(g zq6{j#b&_2H z{go;gD+FKO+*iDjlJ4#Dou>(77kJXYh2eGH#GGcwRyZ$*)$Bf5MU8Q~%Ngb+#Q+r$ zH9`DEJVZ`ZzBsBYA8jf1bDbfZ#0K`vcR8?eIIGHAOp@rzbwJB>sTz{9gYSHtl$nYe zdXK2A6c{u$cF;Q?mmCcSE5~3;{m#e94g!1}ktbwMsz?pyJ`OlRsy>tt6J(k58M2Bh z6GJT{R%{(WQq}RigHka)@MFvn0$wJxpNR^-Q>Ykp_aIWCmx0N~c9T-o0sVpMy+2Sv z&|2sdi32Buq{i-rB}6w1LWRKI3IS%u|3^m%3?sdk<@4pX?%#*XC-Q0TZV>(rU+=(r zR*R(JT*+q5nQ*E)hz?in`UBPyK_f70XcN^^4+wz@c0dSJ2*T6|3C-i2{qj^J!94;B zLU=(a1M3E;(4HCqta;Qt&oxK}gAJoNtun&$g@SXTUu&T)5@)fnK#PEgeFrv0!KG_K zE)ji6nVtSX?v+}?r4Gc-u0F?S>=&@MO^Uto#gXBoE+gdl>|^}u(a@!Y{U zc3*|r=E67&T}a@}J3~0oJ{CYgaR5x?2#^s#=mN+h1bj|vJXC=T zNnp^J*H(yPWL*zz5W-b2Kqj9XQ}NpyflgajJ# z1}T z3Lvls&wXk|YkO|C)wq5ILobZ|+{Y(CrihjehW>zy+aHtQ&p|gr3Rcf5IyS46@NDv0 z!$Al00Lg%G=uZcRdY=K7RUW!0Q?)^FZFnw}eb!Y?_TdRVrl-JeezE4OhSibBT>ZMs zflT!0**|^vj1omqP-sqQ+sU6J^Leudb_4m+_%XmCZKK_R;_Dlc^6VP*X*NBe~NU%#l>ak!Hi?9AUf>OEKLv{@xa*Uf!-2PC?5O4vqyw2{?c z*Y(BBw5CX|y*{ScKZ$uTO(+v53Q~j!EUal`65&tti`+g1!(OOoghinZ( z4+Cc!TUV3@v1nO80wmycYnR45)W>?Z8{^?R;CL4fg+CFkFHeH)kYWGm1frSD0vEgu zd(L@B+oq1L*RRtHaHB_4r_QFl-$?|TXWy~Pp#O4%CJ_EZA^>hss?CQ%s8tLaPaKEf z&+wRM@Cs}p_LoeBWlMph)7r&Bmvk# z&=17$YxxnoU6eu3U0@HRhXx^6Z*DtA#Dw>+ZxWM+MKP!WDIA8MuXV!sUW=gB!BN+R zc>dbMh~jtlT&=d z=*C)3oy1c-G_zLP260k_r~Z0=^!F4nSp3z1r?XtZ>3^e}jN2bqz3JrG4^sq<*iasz zTOyp_U%dtv$eb`hdwxvkm|I7pO&ZgHtL^uEMI^X}gglQm$8$q17U z?}bIANyI2;!hPJF!20!^LVV%9Vn%ejjDTSUjT=KXB0-&PED%Voq8#VX+o>W^O=)N! zYNbT~%SMXL8a#>RS`~Npxt%|Yc$ls`U@pt?fD!7A9^?1VQW35>s%m&&TcRoAEf2PO z$_A`0L1d?|ocjF#U0YHUoBv;HO9J3WWtmq08$sCG&wc#wwI$vw?`um0Y=E^TDfK?f zy1Sd56N{eE+UxZ5?`um|tACx2iRI_HAso(M$!$R@lN8~mCpl;b7$5l__v9`T*}Afj zFzp5g|7c%<+)ppR4`tW3Rm1sA+XLsaVw;eZ;A=sR&!4!W_22M;sJA}k?CMSEfe&bN z`C)rn&}-nWgug{#?lX+iSioAZ1|azJYrEx;z)gRL&c6Ba3hY~{4Le77f%Klv*+)W{ zF_AK;uC)Ra0CRNSWswV`&v#im0Z+$$8m|V8v9ueI`03g;z4#T8xj&qH_$vWx$(0PB z31<4Rf>?zts#u2oBZUfh@_Uv_1!Sp-13;FVD7p3BK1PDnF=g*57<_>gucE;&XBP#_ zYFtfEklju=vf(#lh|QH)0fcWYU@?(00i1ZqJ0~8}Bddxia!sorD)VFpbXP#SiuDmx9R4;s zoc}sB)HW8#5T`>K36_d!2RcyYK!PeIJCcg!A!EP0((+O|Lop0`0mJ1e{WO9j3{k`& zN=KMm zP>>o@lo_n{c{9%)QO*n6d+^6b1qT%aVXmj4K*z+l+d9O;*K0g$cX)*4G3;Zcaw(8H zzng8+Q&`~(gt|Yqz_VeU*EwDD9^E|cP_p*7?Yjug=REB$t>5$_ZwZS&2Kgt->*}ws zhVrQuwsP!)L7~WQeV?t#OeFf`7Rq+NhApRdg%2*g`k8E7c0xyl>GQP+cmxuqhC`{86)hOL80b>TkZi zrx7FIU+n5E(S6Q@b#}O(Q=fohF5QgVoG)XdN#gZc#`5_zI0136{zJHGzneSD%?p3r zn~Kmn9ocw=P`0ZHo3m1x4I`-QhW+e0{>x_7$r7ug=5S!kjkQv7H1AE{pwEYct(752B+EF}NNLV@(9TPC~b1IcSG{kD^ zFd8|$cd$GVf9w0ppH?~(xaopWay(Of(Kt-&e|Z~n_P@MMsh}Llp@6keV>k~*8suzh zqWBW2j8Ms9a6!>(1rVWVp|!qcP~`847BF*@!#yi9AP)?33Hu)sx29SnPd!KmTnP3u z130Kft~m&1C%I`+NR`l~qSgZMeU9 zO_*%?Z6>-?Z;|?U+#1rpUH!Pnzw;z(5RO2aAfxk6xbMyS;$3rFq{#?9cxcx6* z*jM_N^OEKC4tFyCDmPwsV&J?bQKtK7ytXxkscVZjkIrQ>@hupkjs5;JFttI`n_hvV z`lx#Kq`_Xg=Vx^nRDV4(xtc&4;M-07`nYjHlAnj-@B7!M;x55#M`JNlU8;Glkfpbt z05c?xIlYtL)ZY?7J4WXE?6j5^#)Sscj_7_bd~Db5W~b) z#kBdI#UXMyQ(ISNf|JXnIPXvKFfmYeT&clPsWT+$27>j3_PxOVEUmL=tY)fUZ+n{z zRoI!>>S|7LGD5*Y%ah@*D0Q9y`-- zU3R(RG)gskYZq>wY#$4}dnYRBa3518+YDAdE{byy8`DT~$Z9POW^Oz8TYo#!$Eg~jJ3*g3lguFY>|1@P^m@*QR zsp9&LeT|&J9B-9BeR8GcqB*<81PP3RyYnHUSG+=)l6nRo{ z&Z^)jExcMbMZJ?cMsM2KiPt23-DnS(;{H#wNFu|%>IuYxe-c`d#hM+d4#`50J$KDh zK6eB(kRA|*Bp~A6V8j8YZ7Ja}n}+``-`}R`$6Z zJmj1!bifB6qDIrO=Kd7kScr@)$JsHjKUu-l)pKykU-Tc(9g7=Xbn`y%_O3oUlNPol zO+nqr34X?ka@PU;w^n9+^@aGTrkv_}|wU)eqR3r74sc?u&Jqfs&=j6ccGaxj0AeGrgNH8}#4 z_!O6sV*B8I>WPL>DGG}^FC5)AG`OLK$Fp)Z5aane*y6TTqA?YOSVdcIs?rxW;!Gv@ z9X=|)-YYvy6=|m7-W5Bp{Ca0L;=)-7CT0q1u=H>f5!v;AEp@Kj>MmwO4Lws7?`r)q)yL|bV4cH)}BC2#x$04gvW~@{T!Af&kV=LP^ zvwzF<<~AL+J*?!sy2gSZhUk0PXFSDvNjIl*UfH9oXB|bly8U}SuIWmul+v>)*1}HC zm1mH@Ix1gRL{A`hyzP@vWr>x}2r>3^jq@SEIkMycFqchWD;JM>-e| zBEo6_C>itWS8-z_;)aPyuTA|q_s51OmR!&*Kf?#H)uW?iMrf(5fP%% zZqp};SY0XETev~RQ;j_;{;v2aTn+cPjZ^96oy}-C*E|fT-qjl9*tD6mT-3B%$J}V3 zJ!}a1>RYq1&Y48**o1Zn%QLQNPEd7&Z~`Ui9H#l45+kNX! z@2KOn1&!cKw6FNUlrP(}JaK$>?K)%=wpf~lCr_dw$Z7cUDD1C9vON9M048H1{&I`5 zf9dbQcLKr`QtK=1gi`|J$++RYpF>?^TE?s;jV`|Nn5M)g?7b7_RN*35x-s0Pw>eAU z&sJYw`8@M#{w6wM`{wMCP4f_(JKkeMIz4=-`69j+>WD&|lNa?tiKvV32bO)kbi2Bg zkLbfPYxd>af>yIz(}gXJfU1=3@>VsqsL{7ShGMv>qv=|aymUL}K4w8XLXtV7H2Uvf z72Hq72gJ~6SMCwfFDZ8v?olQFeT_tV|0=1U;kC4`f-ld?GEOH-_B&CYEskP@$RPk9{{ZcE+e8Hu6<;;BE zp7o0bml1daOI99dHdj!de90jdClALgg41)BAva!H$4pAm61-b%#cHSp zILA}T3Mr;*pu9X~%wzlwustkGObgJnC{>7 z&PX>ZmuQjg=6Ct39;0ETx5e_5^nfV}wGh3(PBv#Fy~la@0+GxG_Se9o_| zZso??``uyEO-C7#uIBdP($Wyp&A%JAul=3e)lP-9{Fj~&Ryf7v2|iuQ+hU;G29I1n z_y5ddZ!ag}>Oj}}i_iqx`&jFa)N3VqHR~u;XHD1+%^}w9=Wu6Qu5baev5lvMjQwHX zls&5Mp7g9ieQgjdYxus^;r{!I9x@%H#)N`My~{zPTZ05!oj#B$6%1Lui|q%-giVF$ z@~^p1$f!2(GR_%}YCqy-mFnG_F2cDZE=?NKYUXTiL)xGHH2YJ;q`rg?q7dRe*q?7u z3+ATZ;7UuwUMvP5;Rs0GIJr*E9rJ`ig z3_6-Cc=4!cn(Cl4KDE{M)O>62y!E$Q|IT#sHQK4u??kP}0I9}vP3vuhZd>$vqT=Uo zgDqknK0Q7%IIOUuGC|tzV$KS3M0*m019+p03A2MfF!i8~&HbaZWGdI2Z9H%0X2TRJ zr#{2+nnf!3ueFOer`)nT*%E;TO9TT!aJ_QjiGouR%E{w!8HU=OeTJvy+DmrCchP7} zyRo@IweAilAdmi}GfbuP2VAX{f!OIfPL+$PjXXMBibs4Va)&J`oDHQ5OsQM-{V$R; zwMWu)1SSTuG`rGu`nrau2-PpObkBPNL_VMH5PYgi4NYn+78!4*ZQCmL<(iL))5R)a z&>vlou-Wl`XD{d=`!IJKCPgmf;7#!PSr)Q*M!7OTD%(9Y$cJ{{;2W! z+=B>hmEdZZ0g? zrziR~J8wk8x023bQE2K?5E`p&Bb$byo17Pg*_gbIV$?S~Wpm3+N%ErY{X=E#=D!IB z0iHrs0Ax_Z>R?!N0t;`@&|y%2@>yVT!`~O!97WpAV>bVa)LHWlBTYOx&1r{U9`~zT zxdQ*UlMoTBW>pmi9eqlb+1RgGbr;wlQaO89Xxu=mb*KZdt(|0uGp&xpd#0b#;ue|B zA9OSh2M02}2NG87TUVj{6K3uIa@a*)g-s$Auf|+*I%;uR%9&f^??GGm9c9pFxyWSf3(NzHY%&9ri zI0iGkQ4U4a{>|wuSGvEB^~R~B*SwAEPfN*B`cAq!Q&3IArKbAEJTpbRvx52QPk)l+ zuy5rlw3e9JCkApiZL3R{RCHH*&|u9}U~7o5PK*RSkl=weLU(&Q)br)QAj4X-l=a=1 zm9@g=T0AdgH~kjuO@FoB?bA~VQ%j`K(q!`n;qP4&3lD9R(!)7z$nGtHKiF7z{BJH2 zsp%5h;`|i$dYnsRw;+0+>lTT;_X6&t%xT*D0q8wss& zY#0oEDg-^~-)sH_FSbu+%z!Fol+Uj*aYB`16pN@qf&)7hsS-Z99G08DuBS(`N76PQ z3okwT{IUeTndmBcOwV$=pGs0wUe)9ecwsQOxP~U0Cf~728Wo&Blz(U%0b8My{(u~^ zmaQCpmU*U4pEnd0qzELSs%A%{Rx*At$7ZelHCSp)p=ntDNAgl*{KNX~n8MR)vR+|` zWselY;pJC0jNlluopAFlE3zzGuPvA_Nxus;I(mAf2nMCp4hhH1#c>M=8}C%yZr2M4 z;Xvg0kN6);^hjEIT_NR33kb1`30qnG6k`8~7d4edLX5zL_hHDvm_w2CykCfjI`afq zW~}i!q&bwiBn|4RHh*v1$IqSG>o5G`P*7`$NH0h)3XN>D#tgx3=qkYLn@vYaiLpAI z*S*(ABpO3atHrza!vfm<8*4a1v=3OgA4EA46=tj8{b6kMi#h9epkcg!(Rn9>Lpwi2 z1qN{q+06gUrQ{IJK_2ay>Y37z=Rme3(;)+gET@B{cM2LPImnsC9v2<%Vj34^dn_F2G*vwQRl7qO#IOdy6b|6nN5Rnw16u#e&b5q(1 zmtjV)#JD{e0Cn>K(B58xqn74l$FYLQFj6{HeQ`HpH z*x$p`Og7dWmD8nyOa6j4N}pTO8_9N_Hk}z^eDYBH<{n8hR`laBu$pWhXVY1s zU7ML=9TCJc=g&1!Gw^E;UZ@_}k7;ra-sHTcw5>{M?N*j{$hZ1v)=7u*h$*6*u0lp~ zTK6>(Nz6)JRqrp!0@;ydb;K4YRBjpyKQ2Kdec>dB*BC<_bR>TTX$tv?J%e1uT>p?I zo*78}3cqmjL^_wIF`WP--maav*?};vf^at-lhY!SXgn&5<|B+hjDHEQh`KMFfoYIt z8YkIIGr55T&Ra&fFhETk9xv{jf|juGaojvK-M;KZ!uAN<^eSNfr5va@>>jjwwR0eNkWbv?4e#nRMJ z|yE3uy6W0MD$s(5}AQ)K*!@E zKY}3+;_ijan3}>O{gk0&TtHbs`Ll?!`xpFzwC!p4$-y$Za8T@C2>wTy1*p-$*wm2` z-~vbBMn1Zmo0pWW{2KW6ag+#eNPIwfPzv5H1!)Pc5}u^R7wA<^|LIk=Nz!#mNO-VH z2UX1ppsx?okx+fA29Z#sJ=xhT_-H6h0fA00o6>0Um5RHzW95;rq0A@yuAlIr(fRg6 z@FiCh-v=l9KH&Pafa}{L-y&DsAz#WdbllYBsfh;zm!u+{5am#80`9)#cUKh#Lt`=u zG79?ap-8248d_jsb@Wph^_>wJB^*XHBE|^~ej>UKCY8D{aA%rW>dav9!SQWK@WoX7 z^#p3$THPh#jVT8Ql@k@zfzyH$(i6Wo$P(PrM@xGspm6X40U{{@IY=)Wv_(c-2r4c! z4n)%whKYsG}51vuKUl(xajCbXtVksBOjyQ2USsNQE4@L{N=#B`ovtMdr7s2{;DHl;a_H)x58Iz76I=t{!)79P>OiE%##Wf5Ic@Y^na#M4y zkD@*5W_eQnU%lSJvW$jeSB+^Sgc7 z^xhWVB{$Fi7z@98SHyBZ?LPmx-fDSGHc%f|yP(@nw@%730k~Q8x+TrL77=aN`|X^Q z!tzzk%VpHdZL^=8SN=7W99KrPj7POrYO|crb?(K=>x9Zu4kndpy{tKBKg|DYQ!%%8 z@wTnb3{*ej-eJZFOqcdcm8IdT*@j%!9Q&qyb9L&q>6h)hU(*YeSEE7NK0XHPhpnG` z=i{%wGLJg)@BWli=@R{=Z)c6Vf^j{en3kTil6;ObvfCsdgLfWnMvbyj^fFbVhq(qUx0{>%COrhuYpKV^exBWM3No3jz}& z#g#~4Y>b~L`lD8Xjbyz=f;ppAOqe5mV3{pFLn?OIzm5r{0~{3UV(`KLl>vmUnzF;kE)Xpc)rkeCL}->`;uGa4PE|-l-3T`aQQ^NoW2m-j zb>tQQ)#>SlC3HZe`R*#`q?)u`!5)lAph@RD505528RKMao-$>4z%2$r3c&PJl3eO z*n5P>j(N|4=DwRsYjyO<;pPWN%~_ONIw;I9dw+vT)3-ez+uHj|fiJoFK1g(Y&&jl5 zW9_}bxx%A`N)z_E71Zry2ts%P5u}Tj1Yr^$-wY!4WBMAD*xt4X)Rka2MOyx zzxJs&iARbfvX=Z`lM??gs@^i7t{zwyrcm77-L1G=aV->w;_mLQMT)yS#hv0_+}(=1 zZ;Cs7i?`?8d%r(xFWE^ZlgTp^nF#=!iSG(Upj*IlQoz1Y9rgt?L{O@zITtM6;>SDE z$TSXB}4yi$s~MEu&=?!QEX;Z zvyO(Y*ZUHOkW5)OSy`Q7Ttf^IPdfqNzedW^i+{L(IJ;%fKw(85R)3nV%bnrhbKt); zur$(wsQ_+jvM%xK{ij6VU+pJ;v@qIpG7M`YP4kB8r0QGKr+B}=1njI2?{=01xP%fn z`S1^yO^WJtFS`4`MN&||Abybps<9`1(=0YamG>Q2a|xsJ3B?(LH~p*ev`n@{|Cz&D z++vUr!6juRWsXXDbkZoRFsm?phdp7xZBU(pW94WmgH-VBvBE#4hi`hXQWi|_c-q!@jiSi`DbI8_57HuzVf0XJ37-DR2Z!+2C**)b5s z56TahQo#Te%{zpn#jC;x?oJ91jh)1&{B*8!tdHRzt3zK+s6cf5dT+oBoHQgzW%|=0mok&T~)G7ZANh(qoo>zUWnp}&8$9bN%envNAR91Z-fljZ}JD;r@75Hi4pvv;?;yTQ^ z@yT!?W}Yh!SW)Q9+Mn${7&Ke=W`2^yZA02jv9i=0A*4hwyHjae+`A~sPkfzg=vn{V zInJ>mh(*;<^6(jO*}2V*_i$essy~SsJpdx)JXcPbluh$IVLfRyVVcGTul056D|3!5 zD;OK#ab|IEAguTMI&~g)oTUE6t~X04Cj~~{KuE9GL}31XhW4rd;nLjw;bC_E?2VjQ z$fuc5cO6MD0niF9EjV!}TjtIeuFaM}KuS1+OM}KmuM_Xy{DhygWb0oa$EmI}ESIsi z=3&%x#(|{_HP_`rZ_bThN7t#lg=m^b^$QlswdC3KYn+&lv)h>1rL$(YO%p2CP}ibg zJ{hiC=#{MB*@zx5?C_h^I#U>o5g6ClYQgg=nw71XSn*_=kIVpTK5j8>gM_ym**5fj zi_R3@<0Pw#&iOv$E!~UWbE%hV$=h4>LL96eEPWopAtX9yI%M#QyovYBAPh>Vh3?qspgh4MC$4Q;6Jp}l%qrWR9=-Zb9Zk)Bi zev4A$QSEIF9luba$IIS>3@tMi<=bxKstI;o@G_sA+}R@}NiKk$Dt`c$q6^`v_E29_ zc>nfjRygdx4^Hl;_STo-6#r02V3UpAXnx6?jlAjB`3P^_G%~D8)jywLH7o7 z8Z5RCWmP7oF%V|&V3SMYeU%Lsyo^+siCuu7@fGG}l3Mim{01DiSL8hK9A$I>?0*q@ zz4zsNyy#dH5ELMMzJI+_J0Wgq%}cXn9khO5KwPJ3jg9emRpGiOcj?pzt7{>_A{fV4 zIkR-%dvfkEiXNUHLv&ib`+|5JB8%Q@JfexCJpyG1;Wwea=05krX3H%zO_EO&a&4&%KWmC8U-zMw`(%PgHHa&pzS}o)~t+> zalo@ZfLp||GyP`{T6w*C^dS)EIp!zG>Z?AWcC^43hjvFo*|7~IEE0j*oWcUyJDDIn%RatyLa+|#bQnlOM*^Sd`ve=1J; zjT6xse#DdTMu?yGRw?6Ls-mT(5+~i07zepwDwlx=*cJxAE;@zCy}yy+5JK9o`;7f zs9Shp8rx=QXm+8p&(>PoEaRH=A~+p-a>dacG~d1whCY6@Ks}pB1PNowIvHrpajnCr zrD_q>!}ERWLH@l$9qGgf`pJ(ihH)X=1O*M!kSnVcyrO1b)r1N%u#l%l$SUKQob!?` zD}>|SJV94B1KqCgfU(`!T2x6257?}sDB)V+t2+@A_b(iNh0mb~<2{s%q77!ja+&y@ z&4GB>{M_@W3BBnY>6_5ag84FXwUg1fEDz50xBSE)J?ip)>jh#<&u|!{vylt$n034d z*ZkiaD@)Os_p=Wt@BZ)Gjos2lFdoq!q`|A81KgSzt>QLh?q%!I;Uew( zN4~ctvo&qJbn2h8S1z9>9*;F;Uyt=kn*Ru#M|7_6VrmQALFZK_XTerAdcMrMsK0#r z*%%%cA)5P=ZllYOzH~TjOZ{ArNxfIo$wOAtE& zfpl8Ew_MJ;p)j;$&!aiGO$v7l&S0JSJaT*`>pJkenZ*{W0SQAp4_0;_W_=SQd6`6a z7&50}gmbjmiC2c}m|vgGuU4M~{iL1oiMr9zDb<*@BqZUspD8Sy*fD_jPlm!wAm+yJ z6~~iGY@1&UAY6)1qkmJ9oPE7FPKLE&cr+SO>3NC|@;&-`)g9qnHu`heQ+|`F6*EL= z1X*K$H{7qq2V8r%j-#&pN)a?Pp}}|4@ZDV9v4Wq|3eGmOQOJPH zIqUI!Rx*%K+A+cy*@NqCYLtt#Ac+#92p_viEfX(t7QQL1zvx~&CczaRAsFu_zJ7J= zbF$@N8s&UFVwpszq&}OJxa7ViU1XnKyN$S#&RR`P^`417hjYD>?vNvA(Yn%1&)L4i z86$9UI%`>6Nk}G4Bx_0nD+~T*h#poJ`E&Se15V-cnsaCB%(W#$eO24}6?LN?2)1D~ zO{H1alu&9&|4h4TpEb@8HR*B3h4eQ=@SrV)-LJMvi9qXjl2VGtrL)A`CjvR zO=j}$Y;;sWF_XVYz;03SBy9hz(PXK7(OGvM9U(9|!5fZj`3bEE#S>kCh5H1|%%nf9 zq)PkI&H)KUHiQXR2+BJNOK;kjK@jV(U#t#u$R{2%$-0c?Elw7E_IpAPM(WuY9vkUK zohCkI|KW5@7V#xs%(EEL0c2L+Xa83E^bGzJ*yPVmk9q2#w!?n}P|I_-=~h@4ubZORwr)q7hOrQ#(JKs}*3I z(AO@#A3}MoDk4OCL_Ivld3r$dV$8`aK_k~Em|HVLH06E^ieF)+6O{ z9i(5Vt)jzk7l{ICDYmH;=z;EA*O3AnbChsd&fSHIiYnVeF0-V77{V*Y(D0RfV_M9(9-v~p<+HAzmeCk<`S!3#TG0-;#yXTp;q52bJi;*fG?rTx${9Ed0* zwH~vzQ~ETsa_VmS(_BVQ>BETfw9%&Z_eCx)@cy4w`H~lDaHnV6>6IWB=x1|Om)qUs z*&S%?!~bUAT0qk==0?wr59&NAE{=F!=7`j01wv1Omo_Kxm9wtKY1Gz_Ob11N4r@PS zse`?-Gak@WDLAjxyF!=7m`)97kFSSrQQB_Ht3|CRv2SXuSFVDlPt;|wxvp0xXwH2v zb>~Ylg&uw%)gH^`M$$%@_!L!)X*3V{Ax})D+94E2zR32cmmL4+fU|%#G4Tlp5&2o5 z_E~7v?HSayv}dab2j6b;lGv<1&|#vrMjc}@`Fi~bp$OI)m2l-b{yJxI@~PNWnjYR@ z<&!mhBPLS%T{$h1tqJ=6Mk!H48gx-3XM?xwP4}G4$8_1{el}b&$cu#W!-v@BU4@;< zZ(`K5KI*Otx_9|v^P##I%B&*EXt#+s6W~3sq2+@OuYnb(-^WzSzGSf|8u*4WQ+r)p zgfMx^9YrcO)9T%B4xi6i|JH|=4LCy&Y`4J?mXozaJCuvgik`NchJa@bjnZtqq!=T7+_OlV~ozm4Bc zRT53LQ@#(c+m1{Q8wI*ZKS2DxYi*ru-6c}js+6amRLTFs#Ly%ajt>Fz7`rDA6l4ie*sC_A&T_ z%C~#zvnXs;`x=L4ou-x0;IeY3q`^qawb(R=$yV{ z6j8Ee*dmFO@z>1kc8SxuToOKumt{z3Fghx%e<`RN$S&VL#R`*NJ$)iFXmH7?QB(3 z(mFg-y;h zs>|X5)zG9!z7jy~IygLm8k$FlV$HaO7O!#s;=jIOq32cE<59hGbeih^FtrE*Yj_o}}1Wvp1P z1HPk4evyG!GrjC(w<^lFKHP~e*v{&i=uO?X`r`Ar9G76BHKs`O2W2mt?{P;5OhTQ- zE7$YpD6788&a(c`W#oDwjlr9$lB*#`MGFwq+BwOtGxN5syw2a)Zg_luJP*H8Ah;)w z%RyzkbVc}KTQUUwE2WYAaIr$lD*?gPuV+Q?h+?+S=ZJO4dtggU?*ZhQAPt`Idv|q= z6pzGeOZJ=-qFA44=#cG1rduT!${66bvNwR^LAjR4wIeNuUXLc09g1hSmHmoIgFhK^ z)GnfB{nbh7h_qlVbrFaracO88bgTCWypNst)vsiGG3l|Dvq(v(P(zpL>ZwJIm;TjL zi?3W&iuK@HJ! z4PB1v!b&{Rl76QlC%og=`NNOFKAqK6YcCt_NdnhzDFsn`R@2`sQD+Y}P#WfG1H>$G!{Dgi zA$skhL}zGSM)FjoW6xgLYh&SKFq#h!F?`d~;+oc; z`RhUL{-j@_E0KxyNQV8>QpTapz{Mc%(D_4>bv*ZpNeAlvo-YqyU5j5Dp?zGHvoGxA z>+nVFGzMmyhlIuFt_zFQym-VB_|VKB=bv7!NB$5v{t-N>ATODpf7PU4A&Wl9AFsRc z0>_JPt=ZfLtkUq_2#Dx7jMj&+kCbnbb4VK<>yuBBbA`DOw)yr6VPfZQWuLEoy5&u3 z6VfMJI@B3il}kC-xZ}feFj4oS#SWzS>jMYh`a`=}dRh<$!vv%cPd%PBe|393Tp;N! zi=AS)3^gq&%b5In2>7!JiOYuZ%e{TUX99WQ;`u8Hb`R2I@v5g>jL<%U0kJl&wq`*vbXK^=Vd|LK7Z6@Cnj& zh8Fse^K#3aJyH`o9GDpNfV&g$dvJ7k*&hwgQBmj`W8aJB-#N0Ge6hb6gU3dtT|lyn^T!48fAUAycy9ZU19!Ed$)|6`nsp>(128}rMh84KmI$cNcU z(^Li3S~y@!%Y*DkLf_mXpS)7Ha{s7ldn>~-c%}yxkN|_AKw?AauF4uc7O;IWl6HPr zY??~;OYKo&WKO0g)PI3>F>B=>9Q1ArxVEM?ryL#4_Z&?1FZva@d2{yFWj;2Su~sQ* z!NaXAHgc36GMKoDB-g$4Ut}G-f++UR4jsLs>mqnYcym!kX}jgOh!{LMGOC6A)@~en z=B;X1;41XsLDdVFF8HI14K=v;TKdIvC*fKvQ7e}PBFH9IeR;%1n5`R zsRgB+8cB21`uSAv8KPA-v+ikP;Fcscedym%-3@hb&Stb zKkYNVA3ycKfqQ<&HQrU-AWjVU*=qVdmd@Moc#V2^61_)N{&D={gfa6f)cpqQzxlw* z|2rRuQxWCZbRXyz60_vyY4+*f>`V}Mw z%ijLt(WfvWgj-Ft#Kn&P*n8b*p8&OgzC;-wKow?C7>$Z80i!!FHI)IHrntFVZv7UgYK zYR#m!So643M@uH`ksr-%?PNE_e(!#|%Za6jw6eFz!Wb*C&%5N$#mAPwgq%%;eoa-k zRwqdXz2eg*;F7Lb?@+`t!7k6+HTWTZYc&J>Kc|0wf=_`Ai+Sq7 zfT0QL=$pwc-B7xPqnf7oM2B2vx6U&V#Ug@tJ%-2-Jm|%wVeqr# z_~D@`dn?M9t=%N9odyyz$^k8JKe8WPAJR0^dGlJRJo?z#I92!LQp+5Z^~z-2bqC9= z%I6YoRV+s&ymk=WtSlX>j*q>0kPDlf+pn=Cx%qvLRu-_o6|ZxNY~XtbXr!a=)~{KZ zi3lni>QfHaa0{TDaAjtnJE-0VFO)u`i*(X^R&nA(l1-_QiWXf` z$KO6epwjjn`)rlpX=;@z^e33kUmJ#W!&TgyF>aI9InbF;wxlZKJ$iSg(_TgmE`y5f zzTor(DmCWbYiERLp-A+pNc2rJo^s3bMUy1f>_{v*c;KjpuTEG6XeJhT{0&OG?*Y9n zYwdV&)Oj<0i>PEm!ykyDiXtvmY_YmKjdvs7(Az-y=!>fb0!vcK`$n!mD&e?!h@mmxBGDqSZLVP(eCFYyre#| zJ{f)zcW1gyhOgd{+Z%f&_Y^DE+}HuSqm_#k8NvG1dy7`_jPfNjy1pG$%enn#7P*U# zCmh4KtcMNHo?q&CkUW8Xi3!$cJ6GFNR)T|dl*{^u6<TYQXEf0K$^*v&9Y3xkCXg(=*yU1x1P~!{s&;!0gy@qsvMCX3JhToGmV?E^hzL74&U4dK)tyie;6e z|BiK1aLGtP+f^;}_}j~bTlCoGWnzGbK9Vh}*K8M-0+j;B*6R{ysZIpSnXEYI49+}+ zD1@v>BP%4mq6$9aMGLPNI9{Xfco(PFiFM9u&#mY-&|_iO(((-xif$ z+Bt_rzB;|0|C_FEt$m$wP2neP*27q4t0?}qpiBe@wW|WpgFih&+UYV|&_DKszW*uu@IQ#s+CfeGi>U+Jz1*ugT7gvM1pfbmrR9 zM9%l)JN{g~g(m_`0{rjIStlJ7+v~Wkx4V;HA6ax#L!d!2k&6PI%qp;$p~#ibgBl6Q zPK6Dm^ucZ_TP#|OKJA^EZF))#(Bp41W;e_8z($8N7rXyL0rWCN@U$|TG4%>>SJfCU2snTOIESM8|DHp^%x&{z z)biw?H>>}4n^5AfRrH;}<6sc5jGykc{jU@wfbfHRe>)ufk`Qj!++^b>Ga^uHzlfXV z*w>vT&{z_osExMWfdR*r{^SnQU>N^ypqL|a+8?%!`70D_2F*>P&QRWNV19Qu`D@gK z2fT_|j~6i3raPxd*f_{*YaB}-iVRXDm?*)__^N|zRbE|_K}Dr{+D+zhUO6iiA)j1i zDa4btb2_4FqTZ>*72e-fc6^E|Tf`YEaUoRdVJx7@nUw&02QC~ZJH4leBYE1<(J9#a zZ12R@-cH!LK4?xM{xnJ&%w{+0PkU+sXG<4uSgYUTKKD@A`yTs2>E(HE@GdcLKL&A- zaWW+J1#=Cpy9?`YQ|gMV+Etr~^54s!>}4CZdQ06S+h$yuf*Nm6ZsgE~9|7}EoWd!q zyia|fU7fZn@cbK6^L{T&aS&pCo(gFZTjESOq#;DX)uo~&wI6_0vVX6v`U$15I4y3|<7U?jFu zM=JHXrgCg*s)%WrrvMG_=S=9OsLWPjHbG8kdks0Yw>Td#zyrbVhcAIJaKrYu4kylc zAE+~Ic$O346|A?rE+K(9!B>TIXB8=^;OcGAx;C&~w7%+gF>c|2g`{4-D5Mk7ckbzF z#j=))o+n?Iem8l=5W^M_#H~3>A;!vL_G?ar6+&wN&FtL96JN5CeX9$tq+i_B?NKx* zx%?|+v&w|r&6hU*WSu5GZEXq~TImgBVw)0OgPTDR$y zS9rURLKHGcN*I)is6EABrB>plAa^{rGtm_?!xCoLY_8>GCV#muu$9Ypx(M)9XqNPf z$?G*`TjZ#K|Nt484*|Y<^BH z%N)XcA!>4Q&Gthlh7KLH4o2~)P8W<$st0Q2W7XwP*v`X&6rtJ4p4x)&-7Wn=jC@DL zg3CyZflNh@%IVK4Re5Q{qXlRAC+!@vC;^N>UVlAEaRAAz5dE0}tZDJ#kAZwZ%( zz_Y#ECh94wdm%~;=St0$v-sMehpf)=MbOq~fzppl{E@?x{o5kP4+HHfENwMZc%9T! zLG-+EH%?$MQa$8aDiQd}1GC{L5=oI6m>E^>I@uy%~vMn2Dn1rdH{s_J)n#bFA-kKs7!QY z-y=}WDAtuia_aV9F&TK;b*MKRe3gou9gk6Xy#j43uuoz7fZ zD5-cFWIT;6C5!GZeY%HO=z;@?$2 zTU&%9o)mLP%kV@qHJy#Rd{!Zl%jzJ7fO3l(R2g4vA5b;cTq5W}M1Ag25NfsF<7D*B zKoViYp~j)^kgDsQicHyrH)M;!`J@v)@$5Z7PcxHlkR->~yrLAh`_Pun>Y!Wcy2@?K zj(S$gp{D;;IQ|mh*rf?y(jbcj?&>%5DS|<&Qn3F#nDnJ)l+UHUxIjcQOz&m|>exlq z(YYWlpE4^!y_@?ghqI}-4HH5hmUt9?)XoAe(?@N)SHwms+Vmc*0E#_vW{W|}PoW%n z67w1bisQvz!VaXSr9fPYxc1f)H@)iBD%gxdj5Ym)&+(VmN{w>;-+wAFRjMf^qv7WV zGgCI}GU}8e>Bv;}e1I?Gkalf^YdL?|o8(8h8uHL*vMLVnKy*|J!fvlM&@_&%Y4-cN z7&kFT(=Kd4jq$0yOL(2dz9WdGrf}@l+wI}ZyKEaj$h>OCXnoC|5p?gt3? zXRarwr@v5<_x?hq2=jV-KS=Wy|K61ST(;0An8pn;yUlXYR}(cz<7?f~*6PU!$0+XN z=5%esR=|Ys@i>E!os`ji-c`zBCG7f;8ZZtb?1;r2iD+w&D;Ui<(plHo*c;?9DAv=d zW#QoX?YmJUsu!7%86w{9upf>5oW|$EkGB$#v=4iLJ?43j)P$ozwZZtis;>0yv^i&} z{wOBplL1>AsSCvL;@=|YL$3?$H9fSHZy}S`ux*<6^J`Yy%{?NWqjrPUaG;@$j`kyB z^!3f=kL+n51&7_;^_vg{f71|v zugnMV`6fC2szUWcHGWxzUYs;z$&;Xac?7D9OSH5X8`N*u%dcPvYJ!#aY}SttTZ>e9 zv|LJ@dfl_tBI9&bd*?3v5G3{OysnfuyJ|HbJi672lFxRl+mKL6y#jl(`4dN|<8h-6 zQdh{ns~0F?6rn_w05O&@=({mJrdwX>>vY;0FjlrYGM^c7UE z%HcXsixkPk1g?Mn09Pzes-I@*hiQq~7P)3ho<-5w(no3ON&@6MN!=z5991xv@$D1C>SDV4iUmsQmCU+4tASh&$v6Lj97^s*|{A zh~Z+mo`5=oEUlIdS-fth=!kN#@4-uWK5PEDquxWZV{F4pT#pQCkEzwioweam$yFRg zHt%2c^b!G&BFkvF2k-KVL+n!Bgp{hgN;#7(*iBRlM3wrk&^7ng;N>&BCX2-|l=p$> zlQ2^Mumf0VZy3ac`R}yxg&I(8h$`hZWHtpQ_}Rwm%-U>gGF80Ju&bw;~vTzKa_IOY+17yZbx$N&Mb*3ar+oDI%;QeT#Wx>oOMVamw5 zpVW|BvCqq>S(0YzdzQNkA$26ko=t|1l4qCmN2m7=9i4ev33Q@ANv0G4kEu0woRzD> z`y#MUQdg6)T$zv&QVfEdLUNiK`EKd<^YSk$>xpB2yk!Px(OYzR0q0jTija}dScA0z zU*N$TGA{F|x4w4lM>hR?61!+Zf${wu7d<2YZ-vE{JW=`I(V zi+cQc?+aIn&FOfN^5EWHw{B%lIED75WeGL6Klxet!QL9aV#B@CXdCp7$#~{R1}(Po zq0u@rG-R+pNV#jo-@y9(aZvcU4fFls!_LULf8^sD^1YIM7KzOV`y(EhNam6X78?kK z5%z(FB!om?w*(QB7qk&BaZcm64-2_;AwYw2UC z$AN0t$=5K|TxJYI4lofK)xtRIcGXEsddu3({~+!?kn2rr8_Orzg) z2ok^hp<)#=c1_4`&cM15mkK<~L7m2VfDIZlI!SdLlDV>Na9E!Qbhup23V5wtxeLw) zoyZNju=^Pk2d-Drx#hW)e?TGNMu9NIBMXUzCtc(u#h&x>IYhYWJVsa=%Jpe(qu`1* zyJVyacyJ`#F!(}MEx5YcE)NpdRO`k6+N+xTan2r~Hurz1wQQV}3VCrKEz%{D290+f zC(zFlMQ5GAo(R33`@Ialk-t53y&d?yuDlH=k#q+V8UDHAnTe;CyGlW+P%XgzXvF~* z7z1heSx&SM1=E5Ulk)c3D=~hcEhD2^5A>+l#r|h7O6}w%rE6iuk6u+Qa22Kp7lAui zSmw`nt>cF(9)xIi!?#I(ybAMWqh2CbBbHq&ZSOSeY$zf<`(>T+A=@8ggCH$$F3yh4 zCpj-;B*YxgKH}Lzb`amye(M9#InI?BCs`B;E zFZ-SQJ--a9P#4@At$il$g(;<_h`$R}UpC5?EwJgOhhbu(92gm1VpX&?x-fEE$`pB5=j zpq-)hWC9@z2pfNl)8a4{-c^GjX;vqJ>SGr}_z*Yo0TsjEXQx z;++D}jpy%*E)Y*8ktxssZ?`G7Dg4b7!P;GXtsTw#;+vrJd#37d=Yei|)J_8_4B!5! zkfIG|Yia+lw%HW;b+IIT3ocO&c*%2&SomK0-{^`8eDmBE# z&=FriFdk2z6pFplP?vx9;#^-Ks&eddtdl8ZUo_#>G-=!yRzmD&n^2hUBOo~k#1my4 zf`z1r)G*cWOn7_Uo$2CFERsy4C5A9~3m#aH0{DL)!>kj-tYcxTkgaxkPVvSRBY5z? z4+9#DgO;+((69P<6_EkWLga_bw>R5lGMw-0D81zCiAdwn3DHY~38OLNJ8B1~?|p5; z?|Ee+h0;|>#FyPC>?0gXN0`))w?I@pM_VCUP@=FuO((?A!1fK zK!EZN(@LqQipdP|8N@1DB;@~q^) z^XZ4G`>nd2e|Uui^w?=%kFyYyFzgqRfg`b}Zz`E{j=#k!%+qn?$i(Pw(2>*jN%UG% z2-Gn0S20gN@cm+LNkA3F?+m_=-5MGqZrj&_J__ zn}{AElz5Xk(_H(m^vM{h6kBENdFrfde=F(%1^Ee}fX( z+*LUooxTrNPlH`skz6+|EnZf2UX(ZKkCV|);qJ*ig_4TA`>{2H#L6o%w6;qHo0Nl5 z5uKf_pgX2dYRVRqV!zgW3Kq?B9_9J5!gWqzm7)LETWc2EKgK3DK*2b${}atL1x@&U z@m~I+!LnM2%i8sB5kaUKn0$YnKpK-k8iMcn$OagH>|vk?!af9kK33m3)U$>AsGonb zKepWQy^TYnC}D0|;A)zaAwu|bW~rUL98>(89g};Vi=~nawDdgPS3J08JTL<~!20-4 zzc-%kR+`r|VBBg4^9aPYCgp#aSOMVdUgV#UPDij$!?T{$`hS~S$sWYF|8NE0R z(?$rLyBgwKO#3oi4(jKNgIj}BJ;YNn#~gyk{04v}{r`YvOo9Q?pdoJ9)JQED*)ISa zF#ll#jBX>MZsWYqHgFW{FTuW8N$HPH-2}|VaAV8Ma*s@RK8EhuM-L$ag}azfPumipflF*kT-ipy;g30-s^H=r1rW`IV! z-;<}_b8=xtWN{_BWOd4zg0@h6s`pB2XRU#S`<2yM!nrS!_aUft0^d;ZqhxbiB60a% zh5~zQ!>}FCFVpAV)AeUI=@SJ;-n_=H*LIgzBOTm7R=!$R3O+B{c;pg|rtV%|oUlU1 z-xSoI;|88P)(Kuc`||oBIsIag4T*B*crzW0OsAJR3b5<`2-#;Up!dGa-65tRi#qjn z-ZGS&S>vNiJjD>(9f{5@#1IRu^Yluzt?}~l+4S!SwfC4zMc!W~I5%bzFIo;p?RW;G zJPqOmW1WRAw3XAdvYQfNb~icYW(WQLkSJ#cn!CX15*c8`BPGK+ATDswHY3?C*{W6G zj}byAZ(se{HC}R%0G*O1@f!Ce>zgO*XQFM|N9c{D8%2j2Hq_cwtn=o66>u1pWtM?l z2YuzRKU1w|co=QfGiB1PDO*i+D$Kudv1$_^@;5L0i=W(aEn!{B%VA8vO_Ut?6ROXA z_m2*za;o%-aCnvaQO_QC_vq(=<6r}Q#`!DxXWZxcpUEyJ&G3uajyXdvS9sTiJu6Nd znT{T(UJqmY*L#Ta$t#X^t4yoZ{TI@UwfVZd0(xSM5$b#m&(+yku(~$cP2xF~S#Y`n zLe&w1UVl*AzgaaXV8`GI&45H&XRl6=3~71uNPhpko%ZSaZ2Y{aU<^rLJd38vNRU&I zW;s?4{rOIsoOujFg^fK`+4nHLT;KW zgkXViq!U+(A8C5q&lXn{e$ifkk%@XJzQZ%;zVPeWMxMiQy_p%xA!dEOs`2Cue*Sue zxXO+64INk^L3N z^7J5p(%u_r7-Hp!DGVrI1@?U!A2^Y2(s5OZD}CJ5+Z$|<3WTsvB3>jr!tGY|)sCP@ z0aJf)V2sDB=bT1p21#AhQCCxA9)2!?o_Qoe>?u>hOHA`o+|}lSQET0X>yc5=Ce=6! zr+=omhpg(xY$j4#0;}?T|Gqbe|(9}^-DVww$Q4W_d}JnG!f++JD#n$yXIy ze%*)pirEaVu3FRulnJixa>~3*H>CRc8&(V5M0u--ZW6=aQQK~yh#x?X0uJB5{-mz@ zTMhhIWD4w^OtNYjB!B`{gd>koJ3bk$^T%N90hZ7?_=FOMQ4a~EBzFH%VqVeo8FY0i zWuQ71Ks~qgOa?KPbp#yx-GQpA5^9rv5l#L%Ypvw0q1Mo~mi#=Ex1^ zSnBH2D0Zfg1O98~QjDYUDzGqUXus*-3_k=T z0Of<_Q&*wL8xLZlqXAE`MbuR|)t=iwF5t9DX-GYwq(&Q$PLA_si4bPfTQFpjDDFpX zd-C2zAo0D%N|XSb9so9(cD^Sn`=8Wv)HJGJ%T(0L9&^sNaK0rOBgAfSiIxKmZ>|b7 ze5H)5Hp?B*He)_FeV9A{37fsR8s;xLb5%MkRh>cK!fZQU&R{y}&6G8N(UKWVb(r^b zdGG0jfn467-boB7UvCyE3H%CKXo6Y>VhWcGWm~)!O2}j3fGRS1q`DdEyQT^eA`tD0 z55~M4T%4)~Wc(435RtBULiMo>|NmO*FdmTI<0$%T`a^X<*k8(sBh=B&#KL9$ev0Nq zug9jHeL0%)WDcnJ$*)hbIZ+kT4e8jv2+T+{3ERxlJT#4)m zdB)YWPts8j3CyFf`YLEV*r3q|*DvO(U29uTU6pF^|MVIf>7kqtGj)5D-p%(%ysMxa z<5a9@n)ooNOK4q`_eumNoi>Zqfd9i0aP>`~P3bwkhePN;mj58_P#l?S5VbxQ;sa4{ zYwpK-e$6fHRdpRjfRq71Rb1(7E+DrVWB&gKD1i)qB+@S1e+O4(DU`+SQ6D(pH|8Y0 zwPwxzD5-6UFt~I_jmWX<_6MaF$b~E!U}oR{rGrj(_2WA)$*{zL zMu-TTukTpy4dP)hJws3NoEY2V(Ev_-Yo{elKdoeDiom%Idv^9g6p%$r9wJT=o&*}@ zP!kXk0eAq60HVtB{UEFAcK+)iQ}wxK!jome*^q>?Xs)@enZEa*)#LGr4@G&mA>Q8m zuQN8#5+j4qyfDrvK-ox!La!|wraHVk!uJ_Uw?oal5&Dg-1tML%YXLFitM9$VF) zJJKGE207mR{mBterIe?UiD6g(5ULfI1VCuF(XJbM2l`(Bc_;>XMuo)w^X5`>zNi%F&%o~~v;B7h zNFF$;bJ^%t`M6wQS{LTYXOHpqIQCnzB*DrfLbwdtW}HI-v0!ZE?f~>mO!R&C+mOu$ zz{C%NHFlRfL6P{dl+i$6D2r7oyN@_h8vSMAO;x$21OYuG17n+(v`cDq2w*=lfP~fn zj;4NkZ)>EgSmgh~f;blPyv*Q8T!Gk6CLcF&au^5o5xLqwH+b5wngt1Gb<#BDFz94*fwJ%7|pzh~#?h z{j7@y*q@9q#nC6Ts2ijhoy>njs(AFPQ#mgN6W<4ID4Y}@v|RJ>0>hr0MWm(y*klG^ zGaT`sQBiiN7f>GEERrfBf)u;%CL-^ccx!EU`&S?7i{+E?zT%zvh^p*wNLbqCM z=5v~}<X4XSI*+d@Yqp{}@x`40YW(SWOCzR=qPTD|a_@JL|d&$z_Bggmx1yiT4?MAjDv`_uV37w=F3p$qTc z!F^#(ce1vhq4@w;zW(y3$6$1^??=G>S0B~u>TXp@?L2egY491oHGZ6#ZUIlPr}0OY z6)kH53ih!!5w&Epu~;Fjpb$W%PSyC+voiqcGjaaugoV6+Isp%hoq@zB45FqrT7b31 z)I_7uO}gZS_meTLba(QawrDcIiy@_M%({18@B+Lj=WP~A1~lfo6(nwnX-qq$#A}V! zCn)@rhOFxgfZ0wz!{Cwb>ONDMOf=YNP{a@2mO&hDeN<`+?mb>i^^G9e^w8+IHbM6Wew&v8{=% ziEZ1qZ6^~a6Wg{Ywry*of9HAL_xsMNI`!AC>b-Y&ug1cybzj%|1B5Lw{*48dh0;tw zL!=M}+SIBi((QT#zk;9j{CUTs1jOfgs)3_xE#7kbxr>>Tfpg1p{E~CDX~B>Fe0tz! zc%JMW#w4l5Nqmxmi#Tvv@Wr~GaakfBV#{FN#iP2S?%X$ z9RE9;H}T<`GMJ%VVo@y5$48f7?n z{rG5w>@(7kQ}Ij^{o>i#DpM}zMn_lk;^}qHl=-K^nPX-s3hI1w21fmYfMcp8e8=bX zHDp{Ym(xIZ4T{nR2W9B-|K+6)_w)V7OGUBYvXh>QwQSrQvVSKI2zxh#{UP-zbf%sA z=JZ-^WYKay?#-42#&LO&pqjNIOjypu`~&(HogQ6bDCzx-;&Qo~)7w_QJErzdj1so5O% zx0ggzjjxF6Jdu!ll@Ps=V1>SdA7=pT@B9<|rX8c7kSVGLw(U93+PTtxuUA&<{aGrf zW~?Q!M^yRZ?RXKNqIftJL3xF0^uh4>r;~dwab4WG*nF5j8aUO3tWv}2-I?9x;d6R{ z4Qf7Yg^nJ64#`z3_AY!y>(T!P^XxEyWyiepfymSFU^a8aD5+A1k-mAhFZkSij5;XE zrnCo#X4@w%I#+NcSkf3Y50qQ)l*{at)Ap7(!c}2(f435R*SfaQzJG6AJ;|5a6_XQf zr4cY_s^)K;a2G#nXU5iTpaasWpK7qR|CQAEEb9@LFvCpmUZy*pg?5_G>X3%cJ4ZLq zY?*S@c$~gCi0q}wqfJ`e7@Tvw>s5S!K9IQ3#v(zyT&(~$O0 z>BkwwbrnvAwt`V&RtXIsHd+W1(+{0b4OxlKtJqCcp_##Rurz+7h|D(WG=Z)|qeQ!0 zY;;#SUgRxRJYF;y#>zSfFV?78=7xwAW9!}3O8?=eoVq5{Z%E9X zOzt)@%r-Y7VKXZ=Qggx_Rk(TAq=;ohXjgriZg!X#T;l>sktNth1b=6DNgHsvZ*oAD zZ6cGsUSA01tBOEL?W(Solr)MYKE{EO?mwvTH9&VLZ`MzkD()}z-1E-vW7V)$5sL90 zJrqB-Hyn;H<@caP%f#}e&0`~_%4(m^5K_BSEx5%C{iQHGb=%qq=69Pt4&zH>!@Fsi z`9G$jxQ3(W4wvYCD_uXD%t6leuSYUK@yFzQ7jfOp-povB`7Uy(odtCmIcjrIuB7&b z;|DmbhEf3Twz)UQjrfbe~u{cTX>1T$tiax}D;yGXVYhl)M( z5EXlcNeTfc*mVNTxr_;i(4TRo-_aEtnQx5|6-WC}U$p6ed^tvE0HqQ16L46*3~+ei z6w4Hpq&Ok?`|YdFz)yg;w*|12!;%kT$_SN|X^IU5Wz!ka*n$moLDNW(93>g~FjA5$ z?2l+8R?^>KQ_7?Y0$lXt+mb4#uP1Bha!%qY7D?XR(n`OpYyFjt)_!tmIObeEmC<;k z376fafih@G0vq-MU+6q^o0Kwn7t}WOW)$Qc;*an>wdgc@@O*=eFe^r#fhC8rj4;a? z>_0L_nk*g3bo)TgrbfRq_th!O8*Q7!IDbQAoPI1mAv_wiY979K8rEd3CB?-4~U);J+Pe=xLjm>Tcv}Njb-G* zDv#x%{T5uDCc8r<6WzXfwrazy6fZ`uensQn9o~{wHe{JP9(Upoq+d113sbjnk9d?R zv)%5N#CHV7sJ-R`$|j3duvU_57gF0+D@{=g{&S9~J%YelNB1BcR3g@FRDL9XtTMHk1jSl$KVS>gBiWhUXT^+Gdm^VH05DwIPK0AJWi0$Whn=sUZk}2Qq#^` z@&|%*TF}?tLvPx^t7d5li$L(C>HSzzp!N5Z7sG2E2>|g4fVpc>H*23fr9?umq>gpA z<;u*Ygcv;92ldj)TG4jivinB*6%P?X4WX1ipsaYfJl=T617QR=1MY{{LJ9*`9nn|Z zju4RcEF6a&@K9C9Y5b?On)7yqh{Se;dLn8IG4ve%Ny0(R$ION@L0%fjfB+?g7E%N- zz_y^W6QL~Toi&Crc-KV?9i4_=29yhy*oKynhSov~HIH>lw_jcmNyRLPm*T}W$^-iH zyBIG2CuHz#$gcsnclp5ksx(_6*6_(56F#@UmO_~e3x!NEnIj|djjwi>BE7Da$~pI# zot~PTUVUtTi8T5!?^e3Qzy|OsQpP? zhFnFZV4kJqC4IBa(BB`EZ^J|2mPfh-9e6%>=!cGp?Gpqf<-JT8y>J$Cl~e(1;c)xo z#4QTJM2zYAiGzCp&XA&SmjE-QB9RHccPk8BeVJS{SrNjuh!rc?uB7U2fKRj(3lrA| zl&@=3xEZ=hImGumd1BD^UH6axN@;R4Zu=@|N;K=*N54VUqjxpSJ5Hr;F_VCNi>IoS z=x*yQdHmcGkj|;e2d%PIOo&-QB)qLxz(L^eZzI3oO|>8Ye%=Hb=4R)uYj+trt)D!CfTT%d%0_`sTTGT9fh@ z)z92!WL~9GK3g)tnDE||yqAvu(Xjv+OTliIKXNP7r%^c-yRoyVe%h;!q(`9I()|oe z6;psbPz1ll{gmdF9XJz@T1xBGT$pJiCA5NsQK0}FbFBsy|EeL7mbFRTP(+7RO+ktD{}|; zc6)4^>sVV;bi?!=-|a0NzF|Jreo$;5+P*Sk=B)RC02`6!-*c6#V!p|PXpRBS6(c|R z!mG@-wmw=@t$@#{Q_;88I#s3!ff<%=H8y5T|@xa5GA(qhk z#c5UrG11@MM5sg8^pUt3v-6I^9u za`+yU_?tKE)oRvi*3K>-Uxr*fovVM`u`K7c?{z}oyl8@leM6xa$^XvoKheg>Ev$3H zt5wWfP_P7UrC7g-oSoDm8O&BnnA|+wpSa<9p$xIf(OVm57yP2VW8**G9{;z<^0#qP z3umcq-@OpI4mHpF^5+e_r6gVd^Qc6^?GbR}WNfitZE$U}7cO4UvJK~o|4wDb&ZKyY z-%jvjmz7^C;PESpKb#H8xg$Wf_x7L?q zGzcAT6JrwSq%_B<%0);&6C;QOBoLFp1SR6|mI2=qXITH;!0r5Drs54uATL_DnTg2izq zK$)xC)2{~6dEXfjII-K6@W2YBZ(b6av9racls9Sq3R{=qn5~jHsu6k#c|$=Bvb(Zhp;)8_W8~q8i0EsuMIog#U>~yh>G;2@Ghs^EZD8VF<$vQ;i40m#^YfX_ zTm@G1{?-L_(Hcf$bis*=qLVPw-{=_e;xvF>G~HW^m_cs2=xwFM=YelQkdQ>iw+?l{ zHEnX*S+h?QiZK5jQZh$xfeciw2|c!tC1XoAVEfG1;W_zPG8&7+abV-$mPk>*wXX_Gr$9(_kmoi(7C4jxvKd#)Zk&f|Fv)f8*+ZC^5+OBpf5@E)6Y*S`&N41t+tjE8I&xp z2!(|~HA^>CJqKl)QpKIY96Li}x1e(pW93jWIRL5`ig$7>SHT_+FZ|%2IDBY0Xzea) z;q_7bOZ0NH2)%dD4f+W6Z!eu0uO51>n@ELRb0p>}PZcf#^DW*28~nL0PtlFH67Q#| zHg~1hODyNR%Et}n(?j!%cGHIOt5w&~lMIX@;{C+IZjo2Jz;dO-3hpSnyr$8@+9Yfe zLT1{~{RUgqxS0^5+@+WE*zocE6dH8s6`NV?ii^7a{a+3*ogo!G;Ska1DEa@Zs6xLK z6@bv@A4PTP!kH@qP*nb*Uh2@e{T>3FXLIY zq193VNPF^W+Yn2|X;$NXW#YaNUPb=CO<#-2FLSMoMV@(9f_Rev4SSnxw{Yb&${V<5 zwr2KJ^8`<0mzLs3&6slSSUm95ax}ym^xE$(Yg#Ihkd5Gtje*OY{>#4qd{Qi2E%Wzl zjr+%a&(E{6j9~ge?RV>KVlsy-ZG&HVg(-%OaH0D}fAC|%aCCx~G;iOdXKgy9<@BD= za&#K+5yJBZ&S|opV`Xgy%xSvJ>qlg75^wC&Y1RZl7o|cs_7_QJ4HHM>*Qvnw)+~Ce zjqk~hHU8jm6wxRMVpff~UxlC2GH-gUDWtp``WrYbErH3LLJmLQdW`Rc&<43tA2~;p zQ&sxPVOs>4`LOd&_ws*?{}2tLeD8t2-ur{p#r68w#E)gjpJ!8mw&?=5r}?X~!lXJY zF+0UtJF6E$MV!pj+T#521YQt{_HCywc9)+`k|pa*uvarvLVQ;$N5nk*BD;`Ghx<-7 zE-h?8n3SBD@rHpn@aq?#S;VD<4R(wF{d-y3AD7nR-hHqH65m@m%7Ygk{`U}wh_Uwc zAL~d?&#zF#91cAJJ@OtKda(D_7XJ^Kd!Y?0p&cwP=x`6?f4*8dn_%v%=`L*}N6bqz zOL3@gr;ruc6+RZwS6G54>-&lD&WtmDV&NDAjG9O~Mp2Sfk3XSzSG+3|w_&p(`!z8D zCZZWj8>pXms3002XN4IU$=vy>ZlO)m)QwudwUe`hI zf_xmez3~V!Uf2EiuwTEr%%=$na9_4FAOHPZ058P%eE6Qim%gq~1N9(Bu28c6S7-!{ zUP(iU&ut;Jk>^qvpE}6v8blQ8WxMX{8Ac#O4=^%kX=2FSgK*jZ@3*w8h+@|6<@FxW zHp(9FE+)xz@UOW0ok^}dB$}Rbf7|6cPnSTFU-rI!^BWU+3Z|0Gg!GqiQ^w~X?wyVT z&pvlE44C5yS)O~NSI7fNRc z*w!th%6a*{L-cDL33%t<5np5K+xR8K&czt z_Qxg!hG?qS``mudSn1sSJ~sCHz@MR>j@_Osbh|^yu+<(>*jS{pxl9;tU8`jm&kM}= z+EXGg%5_ZzmrD$FJ$V;m7HzgblndO9N8RHt5FDC_d2)M7-5&r#u&snj;MUSFhmB$k zKS~{|=>sXh9eOR08mI|Gn`BX zhBb&ZUZX$c1sI{NjF5crqh*g#8pF+FC-mJel};#<^%N=iTO)8A)Brs zdYph^=lFzmuKk&+IeQ9if)Tt3fdUbDf)Lh6m>}k4J=w72T~B^Z#J_~~Qzr}H!AJlW z!}a~vvyD*n6gp)_8qFQV&<)8}T7>8a63X_?)}1qfk!+?H+4h-$4U552Kx4pFJajGG ztdd-96pxF9i#P;hfd&v#?%UcFCNNBm);4|QAU8elZ?a8uxrS5Spkq8oYHhomQVrqV z{YM?G&_d2T#dS|PX>mrQTFuLvXSNzKo-LvH8^6>C1wf$p>{$c3m#C#8s9?JGft}(hv%YzxD zj1^>M)uCWBI~)WZl6{GMTrB5i3fw8<#}J1 zbvY@};_Q39n{7@dubx8GLu^RC^t@5tMt+k$GrnIfQicRsT(BOCsywr%xp_l&(or)5 z4KmZN{Z3K66BPU|z7bdZ(QxAi_~{coTwFSpr>y^*--R-Z>-{NHfP(5%7Y${(G5oYx zqVnD_XWlqvITKi%351Riw8g%EaqqP`#HDX9L6VV*TjKR;EWbeg@pxY?LAA5!NjQ|n zJC#&drKihfa5EA%2ouG5z7uY!nG1kl%%dVhGH3bqQI>Tccg)L|tuO2Ir(}l8SUnyG zS7^dt<#%a70~X@FQF|KL7^H72NG#jKp4box-p5y0W7D3H@=WdMCkRjs)a{;^jny1( zR7up$4jav&AwOftl`n@0WO4%;@947y4l2wQ7RE2 zbmF*s`STTuFAZ6|U=eP6>ogqCovT1X+M zsE6F2*T+M-ipuzFIi2nCKz9jSTJ*f-WFmLq1B4xvIE|QMD)}Urf91h0=YBN#m=`sd1eHw|I9f8Kc*=M z?7EwQLsLov+E~mXR=p*cwH1zHy<;qTc(!bF(`DF$0Og}{(`tJL0C0(EI`E)xYH_~J z?W?a-VBf>7Xx~Pi-!ds4&p`2E^j#I90OLNj+hvE)cMn9Q@VR;$u!R+Y70Dv&8kGk? zqjosuo`wY1HS@y)Tl7U4>%qX`FC=UMe%pqhdF=9i4L0;$^jmgao`uX(a}>7jBU@ntz%m~% z8yr^wXGglVZXc=dPh$m1TAyC7qgumf+k#etfqmuycx^cf=Z{yfo#i!UPpOWCqAZ;1 zlE0zjQ$5}9UIMRy(RjtRgwI7NY7jp6u0B)nczgP&Om?>SzXQg>TTk>CPI|(pV<(L% zuybSzJx7WDr*#ifHm8H1Qa+H!fp?%Euz&~N>}X)j;ZgUEbKyUpPROd*)BD2;&{_4~ z(64kG6ec?nuAK80Hox+emPMEyXl@$rDv?>6_(b=bw~qIC;P~_b*xnG-uWXtg$VV9y zFT_?{9mI|tbrn*K)Cw2_Gf5tnomD`Rf#7i-2p^&hK&RKvau@r~w`(r+(6x7t`*Z~G zYWJ~416SSkFbmNm_Kr-Wx`_j>xBnDZW9tx0Ak2U*%D_(?5T8p0;1+~@CJX@P`=e*n zXMHz-X8%oz@Kmsan2|mr%5;m0;n!NU3hl5TAEaHToJ12=eI!r)KZqLj?5cIe*fu$* zpw`g0q#pJ5zdM1gq3h3jmjKfs%~S8v-%TX<2G;kRm)|to4e5F2#519eAYe*fWa9cz}E9Z5a(g&LK-n+2Im?1MQ;}O^fE~ zj}=6UED#2dTs4<(_2&hlmp6_DE3x|&)P@|Ew-i8YjKKy6hqtEPq>uuaHU%BWO^~~< zzh*dfkfQf<<+_W(XdLP9%;bO4fjRA{tgKBtIy4`olr8wo=YpR$v`C!TTU8(D(czwT zR|nfoc9)Ko*j>+Ava1IO7=OccBJwMko+ogibAgH^>|Ew;5>`Izuu;XmxxVLkYywoT zIGkLAU>v=zvAz;DV2G&Px@$ouKRzx-*c<~tL0?KV*>leSz8N4%1CZbXM6k@Rebf64 z%m>KQco&rENlA=iX4?$E9&6XPr7}M{oaXHV#Q8`Ky?%81IRnZfNr6@?-#~>cTgbM-18PNz3r+IYU5GiYEH+zW zjH>=Vgwaa{5KqQ?ps(cYfEEAdlo3rso%bsWHJ$_gDY&g8w%q$ltph z>0}|K>4nL4z0t-|%3b>01k;oj(zFc<& z33&Kr3+@U5TjR9rwRfQ;-EtL}5oI`kTWtfNk;momQo=F0U{zvyJMIKvcVFlNlRx=z zajJUT1|Plv!YiI~A(q&niyV=wvFB*RWQKp+8S{l44b+T`_-+*?L&WlLYttXdJrKAn zkZwYrJC1`scaahihPOITpQ-{AWbbw{nPm-c4WB4J*gsj_)Bs6aJD{}MSUS5rwU4Z$ ze!SM#xOdGmo@SGxNe})qSuLwR=EtyEA9bHKtKjSL z_$!-JFlnPwLAp9i1Ba^H&L8PsZ`fs(t{PJOtNJ0h$uMkKhR)XN_r^xeO{h$6 znIaRDwRB=QP{n6@+=+b3c)-~rbT^sG(OTMHZRnlU-(NHF-R;)Hcj!H*&ddsW)>&w? zM4$cHBe}J8@6q-BZENuNx}v(rc&YZjIjR+4&~0YIg`_avQQqBT@73=?JX!zfCV1Ad zn66xT-&iYEVdVX&CGPC=Ko*|%zwfHA;pLziDsDX&8zQ$zwjNs;PlpyQm;-< zi_&cNH^;d=Vn~t1>>NbFOC-ReMg+vNeP~l*0xyc{^I!4RG=D zA6&vvsa8{OToEfdZ)^v>w#A)$bT|G>_Qw+U-i7KHMlZXC(>FU!KUMOc#&sa-82YVVtm) zir;?#a3kthx3{-vsa^aAzPXFtJ}+mA?TK5|YK)(TUh|zg+Kjerinj4@%Uh59h~SH) zxg@Cz8RuP|bXT5Y7l+91mJj{*saRE|BI6bBmi3@rJ+D2lh3>iOraX#$J`dW=6EaK} zNQTmx(MPyr0TQ9@Rl5*RTA;LVlxD z{iq-?X|{EMBeBuCJLemIlHO@0;q01p&P*UJHvqrKs1`^D;`_(btoPLVNp1)BeDfn> z;G)s{7UdM!6}IhoK}sfwup9fvuy;&Eb}bkM+Jm@9I3yV5c#KKW3XPqe#CR9bFC9gg z>-WLNT!Lcp8on_@2KhtnWgW2WTN6Sy@uQ#{l6b*)bGAAfFW*T#P(O;Npr-y$+}w`s z30(;ru&7u$4?+~vp6OrdxqJhmP_Eb=K zwZ1PUI{4K0kj{9o$aGBQME*US{M^viDzNy#02R_!wp3yga&0~?XeTkbw--dg}hF&vr_4KUu z1L|!)a-A>AvNpWQv+NWH!Q^t}WLPtN_q1 zY$aCIf-AAj_e2(F!?6TcS^5PVHrd(PIm0Rs#wE>lBi=q*<#_Bdnjj9%n-52<9R#I2 z({9IXnX-7QNj|NP`#;WvMxDNLgy@=_N}3|lT-?UM*{SFAcdSFBT& zQ%g>Vo3HzNSUM2)p0*vYjb|{dEz+AjHbD?L2og7!-4Che0O>wPOWyCu{hqiY2kYM{ zbd!%pF+qYt875@IbC|exl5LlAC&+c!8i&TLx zXGE+ez4o;s*)zjlKTJX(XNPFDxw$hnZ68TaL;TT(OBxT;3HjcgIb!W7ZLLwW;Q^UN zZ8-%!=E^SkYT>`k*DxK%39pSBdC#lq8Y`&#wZWFC5Rk#A&o?~8t{>k<73pFNwoLJt zyE}SE9W-TA{CDOu+#>!sS6s7Q+&voXGWb4Jte|#kR09w+xw%j}mCX)Y+Z8$(UEgg2 zN?RL;)IrjpIbGQncD+fr_vPs%CF^t6B$n)FP3vW5B*EG^iXx{YoEUMuj(69!*Xia5 zA8-?-@pyB+JwQh~ujuF+wj{-Eoa_N?^U%(W9orDvTJ-aSVFzr-yTq;Tf-E{Sd@8nh zWzH@srg$e>)yAaiFG`d;V}F)BQagF0_5A2XQpB9Bq_{?EFg+5B!v>#glO4Z81uI&$zr`63pK~C z=&;6_@^5l^iRs=7yp{8{GF|K}zg%{I?0tSL`M&Yr=6=5VejIhb=k9kB7q4%{*-W=m zqiR-6&I4)g8%iCLAyI9*##f#KrI6)Sxc-`ABuwS-t`{iBF|8 z`W&!v0be5Lqlq)>rk=CGpPMp>iUiXMyD)5C$&As@k)%`0w8`7Bj4<#?HO&RmnD96nG-qz zi=MVJiC64(EjL}cC{D(LOwZ2Ag%Mq+gJ4tK&J?%h9FNRIpi#o z699_St&YRpVSUJC5510X{iM}TwoEWjZ z&)hpqR#Iz4%t?`r&&~x1*6#!yGarSObw{g@p5Cs3GPm*jhG27iuCZ}8bj*l2V>_G} zOb-wyF$okBiix4IFu$g-3>I(#u028uB|;(8Wulv2Oxpyf8GI}NP{BRA*NRSdJ0Cxy z1nff&RqISV4NVl^sl*6EaO4SXCCSJP^5(W*pw;*@|BBRmOPjGXiD@uQa zEIc4kJrCfJV__Lqj?{JPkxliPvtJt{(=0~UUx#V`b67m)n9?_83V08PMvPbqaw0yA zle?ZT73Gvq(epX|+8wL;N95k{?pr3L>A}y$@$yRtE*Z%Rx}29vqeGT3{n&u5jFFi# zAm+q#&D;VZ)t6C}{s6-}of>4*i=XL|{26?t1mHEa2~~*-+>i;eV9%&juHd}_wMGa) z#h7~XZgJV5h4I;-UfXLy;5x^mOMvxjKUF=cah=IIyNv5FQB0gP&g)<1b22^s_ zagy%hUj@IJ&%>Ido3j?nRN0RHskP?X_kD#o?>y5%8E)buS&YvW7bjRmAQ)jsv&#mO zX6!*cGebPn!r$21&>`GZNRbY6^+Q-M3AjZ0vRHQU;CAuyn)=ys3c-IE4+)H54X1o( z5F5m6Pc1Xgb?1!f{P#VCe+Fp6$X(u%JCTb*zoj%Y5*(K9E2=mW7h|X(SXN+4f zlNDjwBd#5XA~2bM-~J8^C`8nxpr?+lneU_zrx^6m51B6m{zeL<1j_)%_8XjS`LmG2 z5pf-e;8_yfo9v(6>=D)C`XoOGu}b9w&@t_v@j!UjN-pd7e3)7f7~gA|??#!FK#2Ca#BWSz08ZbG?p8?C zXnY)t1>@aSUQZSQ(0he3p^%hpp`(t4ADy6uDI}qm|LOWfT=9styrTdKT8N1dH<=H{ zXBYhMh%mrtHAoE{pj88_XgdV}^|M!eo#*6CvTOJ~%c&^v3bTItF-RyD;zo^Mn#D+e zGV^1lB7vWfq7{J8N+kI;iE~Ln=7)YLF-_zFV*&*p6A>Al%2**~6J`q=dTpNrVFJy; zFbGqSMUY|WD^ou5G)=SCYsB#)i<==T?1$o}lK{fx)sQ_vX*zyH(wt^#iXLGBMV-Gb z&GmYA;CdqyV-B6|-19WoYGV@yZBVF4QdKw3hImX1u@0l=j+}oL2Hoc{P_wTU)Ujy5=M%~p#tn^0|e1Sm>?dO=234bOfkYTgGs=_ z4cK=N0y{GbpOgriW!>%617)9c45JNS7xhN^<1zyIxhEEc0jL;5@0-^=tQX>asq8P% zRWo712w;d3Xh41E6P_TBcXBjNBbFsGKvJom4o$0W95DB{g){f(zfC*bH47B?A6*@A zGFL=0_x~1!$-*iIYY<`LJX2%(!=E&~4g-)`(kW!Zu<2RKfG(H?s1MWs)CU)p0*yLv zR6z`L|IYwi_tgL2s-k`HTEhKXY>4v6-#82ab(1jdOUw_EkX7%>X}PE}3uEWQ#w*Su zPlOUO>mSZ+|NM;+ZGzFFQ18yiF%6-s(=Y3T@p`jZ>m6%&;Qa|ONU>Gs&+ga=Px1`* z^7jiN1-hoS+ImNKxANVc-K!6?%mq&4bBWdB6+s9nA^+`3g*nJ1E3Z)!$hw&t(n*Mo zBhx@M@>Bp}M)sqh&S`;QNAt`)ZPo>USRkE);#^p8)z#7ZdbIw2J8bX$;gG`6k@c zmIr8FjQ=#R4k?TdJaUVGTmLN)rk&ZH-3B2^KYQ2}cGHu9_U(5MV`p1U7%9N|^rBs4 z9m*j3omB=by&lwxkg zPGPK9F^sTGp9~(Bqk-2=4sH>i$%$Mk)dOEQb-GpL`|{RPSLX6=bA!Xu(3tjMX_D=M zjaHhS+Fm(kUd>Pm=>GKKh401fYVe*_lde;+$P z2RqU2obYE9fm-QL5P}x*e|IxRV>7~~FhA_TrZAUJ`9)U@bq-q%wTXyO2D%W2G{mOyoFqvAA5*Bk07ka-FhCpuM9(orXc~$84erS(OF$V? ziWh1iffOHLAR&DFSLPVS6C3qv#PTKeXvi&K)x;~bw46P?)&h%H+;te(;yzUQW)K*x zKx3F$sCkxQ3MsN#uKY7S<#>9HrwN>1LtAbD*1Mbab^EMwMB!gfqadv4M@c=9eNg|j zI7CtTy#y`#E@~h)j6LAKw*ML1Je)~~F(T}6+r#;qfcusiT*h5PFWQF-YW+3y=)x%`m(eyA7h^U7$u9YYTJ1gW=ISUE zwG-!|lN2D36*^+V1|r3|eb~@DY3_MK>w7pdL5BW0j7<0@ zZ=TzbX^vR*&e}VxyX#wka~ga5AO-tuPg|1#Yh!t$Tt={Hhodd4h;T9Y2rgTUCeLt)C9NJfJTUi$G)-_~+Q5*iLgqd#lNMdo> z6OrHf=-x>l_UMB*1q!jaG#?$%>AwJDHR*^NT45muYKb41Mf3SzZiYyC#sfYDO3c!T zfaarGov{OZn&Hi=?5_W~maoCX$Mzj-a1o8SX)PP-!oA_D(+55eMknDe>_TRd@)85N zujo>#kODI`#CvT==k<_G9-=JHvz4YyQ+riz(?+PmfNjH9=Hs03bm6@;C@+BL*7=L) z7F7bCQ)_x(CG=^4i zdjoLwS_?I};kc{-uAW*b)(7NA=Z<5~dCz&_ty}{}rNG&b_;v2KbqgW~8O>LocvFHq zgc?j5h{#@pGB*d#yi1bC(A8*6_-r;glxYVe6-`mfu9K+hMFKUo0ygNN z5M@hFn@GLxSCy{dj{+k5P3etHGNr$a<91JjbOB-Si^L(@09>oNM;V{j2=5O^rWnQn z3}dqVOp^l5r6;y7(ti_JI9ehTk8Xnkumw9 z7DW+@vB~z?Prvnj0ZYGdiD3H5LT%E@G#VAc#vBhX#M#C`j;Q)mQ^lSbDS&mBq&MuA z(lJm)Ggg>mm!KrjGw!r4p7n43gOfu}?7I$TAMhfi!&6LDr(pUvUb?QEPnrGKDKHPj zkrY1snTkO$yWuR7kNIcF#m#Q(O)tZ~@@`Vv()g=|1PZrBZ=+1hV*wRcGYEF6Q4*zN zpiX=n?jM2XKIJw)Fi=bZ&|^s;0QXX&gs}Bkbr6v^BDFqd4*(aa3SuT~4IO4F^`q+I z`E2@8^qd?^?2|AV0DA9^iEaW$pk`Nv6pw-7!#jeUB~su!{6h?ARwJIEyI zJw=0kWi?H!gM)?jU+4~j4McmQ(n2w@$bYI7aR1>@g5k)+Sh6Q?_{BlV$iIShoE9bt z=7ir5*TVt<3*FOYY7dSi#6k))Yb+`>k{$o&kQn>-w?APa-{CRy^N6^w#Aw z{!mTGB{LRP95IUjqeGJLbxtAR9AYX~;xbTC1+_R49jGsu4_h7Qe?7{U`UTTkh|o(EF~Gz!$F|f0`I`Q?B+Qr0W4Dy%H3|L}a`zaG_&0@_w{z9J>Or3=$|b zz>*cFKqgiZZ*+Ytba~uv37QgN)rsiCRZId`0(v6`hM7hAt|!a*3vdac9%3Q`5s(zk z^Z+!PCuMD2P|!GjkVEl-tj@$ePHD#L5v*y=GsGi*VJHegXV%B-^R1#?3jj9NgQCqx~-hk=T(ZAV27K zIj??5U7-DWo#?|A82tRGecUz`qR4I=Y!VR*^!9Zi;?)Q{+4lVq5_uyYfRU6Hc9m`N zUoywF%S1-Eyk8*+9<>~3I9fEek^7?GO%%Z#y-Qo|y{dG57oT$MKi63Nm41-8Nj6=d zoodU{FX!sp<+JAL>g#F0^!k#qzV+s0?>ef}(bm@T5iVVNgca*#%`xcB=3|-!DZc+sKO+IhWH&a+_s~3wa>Xqm?1z!xl z%)8@qv*B+4MtP@Imd8Kc1Zizj*_}-2-D;@XsC}Me;@!9$OJc-Y3D9GJHl;<~ay0O} z1ZdgJ8{R2zvWNy8=gjTwuUC#m>E5kHd38`(-P>h0p7?Uy3dFJ?2>_AZrk4?41_D#M z_rGKdhsKEcVg7GBE$9P6QIaaHy3~wn_>6s97R1}P_X-hP?riUj?ad+=VvjI;4zx~$ znh*QMjO8_axz8WqZ7!`?@pt=@JEc_&MZzvZ}xgl!BuWKp{-RG zI{aA?EM-$ZVLwh4$J?0JMefrbaw*$jopgHF?yeaRZaH|2Y?owpH@A&iX(`6v`;O-9 zzij}po)eceAZG*RN19z4C_cB+*A~1_6h|?%!%vZy01~4qj15%RVfd1JVsVt4>&^T< z;&R{Y`#*G+vc-Q;a?C%2M38qEJo<>mm?MUFe%r~XzV=4WXQK&~F9)(m@NhW7p4zol zy_eD^s4H4FiV)(*b)M3SEpWrlC^j5soTTKJ{3H?M(LL9Glyrh53?wyjd%d#;UOsE| zz+cbo(N6!qJ%OUWBH%d(*at}yRiBQ|79P&I_Q zYk9Qx8C3amzWzgV6Jj%%>-=&xHLoW;)vj4}8{VP}K3AX?^hP1cP^0U4#8Df3R=b4C zOZiQGrd&|+kS~}IO$h~ldM(f+yknFXYl@vuv-pu*tE&12Z2&?xZ6=7;u3J-StJqz<~CpinXK?+ zy=NbXU^nOnAfy>ELcXjMlP>0%ZC_NDS-Y3%*O*nw3mKgTec@#xreCoS4h1mJ2+xOg zAi9@zkaOBYki(Sl(bKz67n3|jzK1DC zlv_52{&K;)%M7^C6bL|v?J^T~20owv6S{O^4LFg6GN`cp-G@A241nrG1Be0uc(ax- zyjj$EK8k{vv8cgvW~4UJm%yhYQ`ruE3O#z{zhMUH_ys#Mk>mcheqn@%n3(I#`^TAeeE9?As;1OP_}UdsvhDHmxJuH(olWsPC=f6wA2Oh zC!YJmN8ZSMV@U=!}5NAa#sLg-XvLAb|$v0TrwG%#vs z<07sc^dS@$a2Y|RKMfV`FmAu`v7nRf74@DL$2KJ0t)meVjea$6x zWEGM{PH@H2B%HRKwxv=!fFZpAK0+2tq zUjGmIgCCp!U->iO-Om{Qdu@>Qa)p10umMKUn_`PKBzM{MMoT7;Az-cR#23A%)p7fo zeLb2geQLdIPhpn_%su-g8aa7~qJMs}`geTRa_+`c0qG3oTRk@A znVFy2uxBc-6*-1_F83O=@yV_dnKg-jn6=db0we+pe8$2SpBui7vat=3q41!z%e1*WKrhM2>OYUnu9Qx zM=V^6pA&{1Ub`RhUm7#`jB>%dOEwmk>sxviTKJvL9O`@5E4> zw6Jk8ngR<{h3U%Q3RFQtrsy|bYRRZT1uzIIfD@5GlW;(_oZD?jl9?IQK|`h{9yg|Y z74#KorDEp;g?h2`1=Mm%wkbkycp4!SH42L6rld3PFE3*+M`-cz6URL&KOV+)agKaF z`|-z%yM5msYHv>Tig?v)(J%7(J$IlyT`_n!(@D^+uR$h!=Et)Ty()PsX3ueQ&8`LG1dk!mwOf5jm+HUJ(;g`r(K_C0%q(3pHk1gGq0)2^ruMp zW0zwHdFiV|hVZYUzm}H#Qks)I2ZbGLNP) zLwO;R=T5-cuSY@&Nn>{u*NADnA&yVsAk*&Jnx?oKdkDD%9XT+0GB)=Cf|DLfp@ZP( zz0af}-XYjoECu1_)8)}fv!O=%C(7)eS@p?BF9YMcp)6wm zDkMMDK1M&Ob-HFAp*p8@Ciia3EWIr@={G*fJYwlnGAWz9nklY4%PbbMW$JJM&oe2$u?zPdm^L!N1k3Ug19^L+! zK4F-6Xo(S4#9e8P%Df_;-!$NY@Z_cqI)}bHJ!HPLOlP)6g@>EUP_n?>4{Erv8*&>* z2Y42XZgdjw_eQW7RCMjk^KhG_GWl}_22;Q&Af`tP9Y>xx1)2lC#{&Hfv_L}l@4{;o z&+xiu?jq-jxAO%{wwqoPI;hxX!kjoelJt@AzZ8UMq8rH(BBOY3rV!*<4rcWUcUc;Q z%+_~c#{=XwUoF)HeB5xGaFnOfWqG^I;z8mkHv+pT!XDhbFj8b)8i~et7;k#7cjSCf zov>L_L~t~_IV4#mTJ%p8M=PYkBdW1A(QJHlqKzTsQ6cIHeEq&n1&%xre+jDIUWAIC zARIlo^Iy=5Lyi$0t6HMs9P3p%cUa=XOA9frznKVa>N7nrV*14!BO7vbobjGr(Q9C` z{`bY_B7&u-ZfWqoH+fVqP@fDY)3*`}l)o22$4Ix=_FPOJ8-Z3|bWH0{@AB~!qul}c zZ|Aw+nAUb~z4L=a6u6ajDh>BycA0yr%a}jaC47IpkZ{Yt8E^11Sm>t18Vp3Cb49{0 z!iSnoZ9`F=OKYJUmdK9uuAh3)i11$2TF+KR!QcrYy>yXxeY?aD(7<(sWYnv<^MLV;tnGy%>jZ-U2Z;Rynvfn#*hqqAU!I)9$fXXVL z@|%M}x3tsk?6ry5t(=Oo+CfJr9Q{clWx>rn0?7jv(|xOY&4^tR&66v}pfEdd2@tiR z#{a#PZKukDA1CSeUBB4t%-OCU24AV<9u=*liw4h%l7aYqs*~r6*xnrn=aQ^TZ(^{q z1_K9UmR06zRp1{+s(J%a6@B(nni-6?WwbU`OIET98YL9s1Of0D5NBhMF@lp}E42{N z$2G4U=ovrqX}t1_7!$U;dE4qiaNBJlPBj+Bw|G+Z(1AcTI6oFc&!+xKDRe_)F zK3lQ@Alsy770+kZ!!z5^#&4~gdRTjxzA^D?Z8#nX{?tg5jrxuqX9k)9OA8i!gKuI=sS~cRR?Ua%f5H09>r!(A=d0w(`Rpr9<3XJRcM9@g zc>4p$6f*cOMH>s&6&o++d4BS`L&(OK|C;LLW&e%I0c)v@HU)__rc3YNk?#)63K%2H zaTgLILmb1+=8_taLOS~0azz*yEn^5yPgI&}x(gOT`<-|ibZjo$-4!>LbUH44Kgh0epfu(a{}GJ(cmx_T*kDZ7R^ zCKD;O2l9*s5vX`9`_9-oS?|p{_e@WhAlGn6ZhlsXAaBZ~HNCiH50LO~fyW3)Zs2Z# z!?F15dhHx$s(DtDZ<@b~45on#rZX&y)BC5F{QK?7=v5~V@XHOuO;dYCX{6YPlN}2U zlTzlUil?Fzp({v?YMvwXzhVwafs1qLhr<@QQ&}&T6mriU}Glg;s%Ds z3>-k=M^VhZv<2NjZ`9*k>~pGUxMG-O!RZ1$K)YzxUislWUze|t7es_G~>TKvAaNNS1=T>7pOj%BvMd;eRt;{wF9CC9*L zCOFM(remH;YW@Sb-e-TH9;cJemYjZGm}dr>!Xk51{`*kQ^BK*K8Wv@NUJxZAfHpxB zdXYFrz!NMpGTyy!##?3gyPB(8*SqP8?{1B`sLNx3b4NCU?)SB=oGJ#tc0i8)1xMop z{Nl?oLJV`@k?-r>2}CKzS~uIhz&zSocX?84E37a-euW=Dp_L@WOuX<4 zl*2DW7x)Jd-o61+Ntb^Ro)K--_JDu!A!5P2RboQ);{`E?LO`rq2iJR03kE>(3N`?` zY(RbvBG^{V<91;x1E+!stU^vNAuPSS1rCz2FA2ddwNENh%O@IGcv?X)|3*ZtqP>NHgQUY6>qqo z`wN)`JkeR#^PGu^>_DE;k{DY}pvEtUO0Jgp5UXd!vW#y@5vhhIKB3nu+XIBKu+{rTETQ6O;sEq34-Dk`Q1nc|Dx51 z6Td^4K*r){Sazk>J{9X)ncfBEQvgw<)1alD8?RdpI|>IBAT2G1Ka=-m~{# zpMk}&10H&KGge^mIWmsZs9rjB)+;y9aN3h7{*nc*RU>Ux`<7RZ>F;0;8}3wCY9R&C zHyWS`+d;Q`_3C2vH95xRwNRQO#N3fueCu1EQ#YpH(lHAzF;p@*ki=ffV+Jqxxbae9 z_y!^oax_kTsa2YOsVzc|FNha#ziTiNQ+NUNCUsz3|DxXPd=r1W!dn`eGRdDLl^P``~7Pz=#yG|Oz93(Nd&$SQU>WW0k%nuZaioF>HpGJ zZFcn`p$q8mibovf^nHJuBA+5AJMNCQrIo{@4@Q;X$j4%X%l*y}n(}{EkkndfwnI;G z*`!9Tcp5M7c1yrt@Irrf-lXQLa970)h@b+&*y5J)Si{KnvsAGUw$zr@V$vxMr_nm0 z-iBGw0L{>lru2e|(O@1(MS*cfsL}K<%Y#`e+n6xKYR5T@}Eual$N{(Kss4dxham88S;{iRLWTRA&3nLyw6Z`4ex3J!PPB*B}cHlR@48?5`* zk4q0BS*dyO?dJ|kG;Y>R0O_I6SKlY^{YPI*_TH@SJ`-EQscX`wS8#InJxR!$FZ&W! znZg{J2LpNyPdNh}`pZJ1AMe-KFAp3^6sx@5aQ-spgSTD4K;~j!K}M|a$4RFgqrXZB z7erOyD^vBpE%Q&grdRqp0Rr>4dvCqK#R+GYz6l*u9psM#+oJd6to2qOH-?XqSv&8U zDzJ~^AV0@pM+7<4WYQ~MOu`xSupYo3JNCP6tsB6MaqXtu z1|F<4IKF5@pLXCDv`U~r6|Y|OmrSHuaxD_LK9PM`x^xnHtd`j{?lOktC#E-sZjv%4JXAwg zChM7-wJt6aphH7PyCYM;TtU)Ljn_Q3Yo(<*iXQQ4hc`<=iXvKC1DI2k+Oa^ifY_&= z%xNmM)Vs7H?lc&C*%UBD@X7WoyeOXAI;f?9SoZbh*Cw;)p$l7}nRyD(_W;|G_Phgv zfi@bq=-S$;r+Tywbci2#93n&SmF^oA_Xte%x`DbBW!*S8NTLyI+sGj+oFA52xhpxt(wMtvoQgyK?U zJRUVI?1~ET`PVaLdk|CR?si-?G*522+1bH{#V~(; zs(wrWRX@BAaOoQb_rtu;+!;r$4SVcfZjTcAMXld%k7n9gtejgjbmT23WOX0?O0%(V zRwh1u*Ic${8hLY^ok&r=;}fn%?D*LH@a#`eg0y%Q&EnkuP$!N_PI+Xz&(wC3_y+2U zH+XZ4`inL0u@X)se3soV_d+0X1jD(5EvSWG-uQH-=gI-eB~ zt&okSZ7!z&fqamibm&hSbLv# z)@=5mf0(PS=b#=hKa2SO!#)*ZUs!t|OZ4q=iDe6Z0^OrmXK$lQ^NHhB`5k^G!M9g+ zZ{vIAEABqm?x~w?vWCI8^x|3^^S86cOw^%IYyzEqCyOlu(ygyI$VAm_OKM) zbD^y>Y}|cF6eiHOy_BbEmQQHrq&*gf4!All&Bwm$sr?M+ONU@>o8%hcSAMR$+t8-c(>XN>MN1dzQ{8E zixoWU)(xqJ!Hv4dx^SJZh-jJY_R24AujwCP%-=+@8~0434!yNwlX4zb0!r89N__{N z;F;8B)Q>eB6>ucu<>x-(_GA6{8yotbN&|OEwH)r%>?xgJ8FI0=zpgIbGS^~x;5GO& zLLl!aP^C^FKyo!Y^Q8L-()h8*c*au*_)l1BMk>M}XzifG328SzQeFxp-}l74ou6Dx&F&7z?$Py{ZFGP?H`+4UO=85pO|8N)MD@;5a+* zp%&JL%9)t)9n58Z7RyWy*liv6J81hTZO##2&PUN8xg`K^+?8e;iH~Om)pjQ+!?ys_ zfC^?CeC2!$r}0@1iv6srj0nM)f~n&za9bsZ6|S3N z*xnNMbH?;8KuE1oFLuJZSYp_76HUHRAm{+$lN#Z)QTV0Ddi4*I3?k|LNLu8(67U@b zS4gxtvg>r^gN7wc75BeaT~xy@f6+bX5Zu`>#yOAlqDJF+;tsUb>em@3nkzuXqHiL| zWNA$&sHo#j8|;$@zh(?FcIx>km_TPg+q%6ziS_6I{!=Sl&M{h~K-2FjWC5Dw8{H_Z z>g-c|7s6Kcng-jKEpVut2TgRxtb2H3Y7Q1@FuwmGZ!tbkfgmu6q(>+@4NB1!PF+Dr z<+W)>d^_T;Q*!${*7hvs0i-C&;zazafkqJ`9X>E2f|%If{waAZI5de3G^lv5DV#ID z5wl#vFVK~-1-7~{H+nx`ML$5X@qYBM{Cq0N*ykKj!l;a!-E5r2V(KGJnEKyNUC*?> zxKV-0E*jHe=`KRFd>wcDxlzM@ono?N@pN$_h8_a~1T(SD4|q20p41t|Pc0|d-jRS& z#&hpyr++Ai=i8%o?1q*#xymBv{Xj;qE|tlsr!&(lnecIhxqW1emn>wtpYQURl{(r` zi?PrTby4kv{{si6SM$Fl__iNDDjImCFU{^3WkF`)C6lfb8}0J07#(x-<3n;(0og=02Yrd`^FKE-c=k@9>M*^H-Fof3S|lAV^Zf*;pwo7-kfJ_6#!6Z#4V@SebJlsARIqMB8{5WsnfLZyOgbqkODLv5w zFRtw!zW~hU4E!kcfhoxQ!V}mX++8o3>Kb_{fMvql90+j&t%A!mpJ+(eZP~3}+OJNt zj?6vz8t$KAtQQGZVbFPEC$H1de=hp<-Ox1T@4s!XJmv$5rrPxElowa$yfNr0>P#}W zldatu=}FVPSKFU$8!VAPw2!lA8r<{{)Y$V1q&Nar5tLk-rM=>bBoYOr=zfF{fq$oF zAYOoczOA-U0cXcmAmx4#@0!JicOGMkn-zNsFjGj{V-k^#^ShhD9Z3376jLX zd3N%))>v7tnm04s;r$l6{%#uh`&bN*_Ok1;V(+qJh^fuir@514*^5@7@@uhHXgCRB zW!UH0*C5X#j?=-LZ9+240r|BWc~|=q^oZw_+j5##f_*BGHu7*Lvb2q1J#(~^NG37W zUB5^2c94k6P$sFtl+7`i%@6*lSl=qSHA?<9Mgcy)j0$h*<-BT2&@aM=Qkk~bJD>ie zbZk=}!vQ|yNtX0x%fE&9?d#zhDN!Qd^-w}YJcd+C?IKu)xj2TVtBrSK?PBg7B@^}m zax!`LPGvOJvP!lEM}wl1AwvhQrg@73rqfQpgQms7K><&En^^s&KhlY9_%*<_fs?q^ z?wDKN3NiyXe)5%;u*q$C)(#tk7R5B0!kX8n$+WbxYEWC-q}0bn?!yN+&IGh)(SA%I z#ob_|r%?BX%4%)fQ^&z_5a;mUtL*?DuHvym-xGB|8VE*J*IZ(;p+Emm19vE_K83AY zo!xgkO4ty~s>3OR*f=Yv`l1RoWHJ&Sf8`6|J--zz%Xs%{7o+Bp_&E|{#?Wl8reyjy z(4mg2_}jrN@mH+*Gt)^Ib*}Z3lH#3mWt&24n8*ZrMAsDGm0{oy z-$H#LR4hce-ml#am*AyZZT-wLUNyvmC1(|>%;5x!6&0#}2DLxsinhr#bE+jAqX`zJ zv$*?G^(x2kjs?rqcOlJ+)(IZHyd@0-o+5XO7OtOmMp zHPh-!RMpjgT*=lCRIX^J@Rcti5L!AX={owoRZ?Ss3h-kV{1Eg=OCONese1C->9WX8 z@KC%P7x~^55-5e-s>QKci^&g=_KAR?O-Auk=eobUuq3tM)9}fy@YPR=i8P;1gMXZV zF6qQ(*KPAfeMwK4=(m#k!E{Bip7ps zV57yxR)L=;cgl3|ShCn;9-M}YbRyacI=-G^YQ7h|A>d_uIWV(*S?tiQ)(-;KRMmonZo&fWBjfZh>$ z*pHG&>ihixxJm05V50R%homO9eH)(+U}NkN9ZSEJny)gHqJOQ6AZu=G+Bo_YJ8)6h&#CRLT~i=Dxe@ zKx+kZH^>0E+OxA2kGzTdx*cWfv}x3UmsWzrE;uCzp->CLC@d$^1UZuodRjxQh4H^?7eIRYt== z;s{%%3U11#Q$xT{cWsJIA*^;Ng@87s41?6QzZ-1^A|?YE#_{(laO`?W;Y6WStV}Un zOT8iFi5xD^!0+6dRZ?Ja+4yCnLzCaM*8i=&Y4*qnY$aiFnZ#lRePuD|HE-Wtp0Vcp zGD5*wuF0*Yv|(%QruOrM%Xn+KaeRb)D9Vk8q?PdDR+jjoNHI5$ zRTOv6Nklm6FriABDI+(=!R9MenQ%WBK%ILVnbj*DFhw+wAC7Vlq!&sFrm717FqpPr zy_AcNW=^lsrw88pG0!xSLS=xV^=>v6jt`6f*mgFMreGbeLd*fHlNT`2Ht0#{j5X zeeHV_`i~23;!_33$pV|blI@g>#Z`juU5p0t;Suf}PB!pB7?N$myw`ZUkw) zS8aU;mtG8yvWu6>8=5u>9iw{vNy=J`^*QB^~0jrqlhJ)UWLGWKi-V7elcf9w| zb={hm_pxnf0gapG0c~e~|0?Ui|0@4~)f{k$s?a+5900<$Tl0te%4qKjUky$b(RY7{ z(bLd&y=steirS9yN?fY-OfV)AN8UCWQ;xqk&Jg>O2o(;^7-Yz z>{a9|84~>{s#SD-jg9q6gh4loE`7%+x^#J$lG8lvJfC%ciqSskUhR}z>YFoZTjH19 z4viX6Hqv%;Ps>Yr&E`eIfuUJ0 z6jARJR=^G0cqU6$3^J0Fz2%mvbl+tsHG%|0SlKJiL1^mUfliW7XZ&&tg``C z`5lldbUkY<>E%uX`OK~V^e4Lj!o;mZMhJy?B|#-3SK_ktHPD-!_4UzI98Bw=X82|} z&g~{}H&r7YY{Err)hC}Sm#0p|8IV?wxDGlTlPWM! zl*EA>8w<2Az1Guf#tY6--_DCp05$U}TvZqXocqN+kG3mMeRrq`!J|tLDn3#J6{slc z7CwC?=JD2+%BV^{hg2^H1@WXpercVmJabGn6jS~w=>$sLw__AIeEqxfcp5D4`uAq< z*g_IfhGq}kA?$WD@i94bm|Mg5Om$ONA;LFRoFOimpiSIETBBH*4HFbN2>XHh8Z3WN zzhTT{WVK)q=$$JGTu|m6S~1qanUsXhTREvm-i3@~56BKRRzA3HbR3_3t6lo^b*8>g zlS)A$VsyBSw!Up9@*PiIT?gx&o8^4Wfbrk3VOR3ohz9R$ zk0n6u2C`UnI-PD#ULd_JIrYig#0bl}80#Klj$2$FSiP4&ChGN@yc9pM?929eRp)I5pRy>@=|?EWB*G<+c-sAPlv zfq%kA3f?(Db&*RECg+ant0?_8lsUh8Qle4h=+l+Zl?f78zgJW%LidfzchHl}W1q;h zOfA>+8sAki9G`+o@bvxo9Z5>$$5eH|>J?s&I%(IdDXXHlXzP3GK0*8gs33 z)~Z|k21>%$#nYE@)eQkcYEbU6H5FMuddK|ph?1KO^bFUYFBxb>@n#~)yyYXU$VLbG z@ayxbjpBRz^lG@P%IRs1YPsm9GTqscoHJ+F7tOhq3QPZz8no=nZD{&P~W@|FZS+Rx!Im6RfY3Sw&0Po*Ue=7vRQ2l!-LttB20M z&~-;>H&)gov>3Q%e&dL;%X3v=p=eUH+Zq+!$`)?p~AT$gSe)UMp%jZBk0XQ%6NG|o8__i@pSOY9*W`A!lXr9?CIPm@<6(O!61X}pJ-^f)%`5nAp&(NY5BGm1y7=9rIvGQ!$PC+~C ztixTW9NraK|F%s7?|l29zD5xvjTYiN2EwwV%ufy>M--UWPsH(0mFuJp)94S5sj)5H zu$}9en8h^(^rj3~(Ypl!odivI+TND|6`LE?ds;2lI=#sXtx1lNKVt&w^N|se?cwV_ zUYEZ%QY8TA##z4ASO{2){QFE7DW1G?&1G*wAf-HQn3840DqL+BU4 zDSju0mg$Nsx97M5488PJra--dI!TjC!DqF{z^woR%vcZ*dVI^(132W2-5)%smIt=8?V}*;?Y+xU@r^k>-)EL zPpMgJlwQ=ojoPGEj;zQ4Wjs!sKu5i-Lk%og7zQ>6S@>RGbU%VigwXj3x}Wuz2N&#P zhUIZztUZ@plT|m90nWML3g|vEpwsf8OScgN-m=ZKJtJ<7=6eFeT<$w0oI50Y1ZesX z6gIAtUqs+m@c%Td5%2Rpw`UQxQS(l9%-JyL60YD^t>tWMN1Y)!*tjlwM-aETE%h&+ z`<)>iyV_TrAuyu-XyIIN0XW$w($h0KL#*JVt(?a~_VM2`rG!)nj(wb_zrVRCjp>r( z%m`A;4$|^(ngJAsb);8FdilS?IFD?&4ktorkhO0})y7xA*GRIJ;{OUisd3aGO>Gn_ zef9Nqm;AP$Mw-^yBeBJd*( zp{+j9+5s9W5Vl(sK(h$gMP(Z)_;I~$TC#MsIG=>K+gAveB9YcfIeM`{aXQOKqqQ?Tjz^;IC(T9%utH!Y4&ddj;-Okz z!SE>OmzMa_|H07}m3;#ri!ndX z#H`=2^muj7I;!@wc&F>mVo|Gi_cWiYlaasy}U!G$c-X~D!ebU~q&Q8SgMkh^T;y@h+Sj2M_+w}at?4OyKum97( zJs50*fGqEY*T`C!(O#_UTBdV3Of=n6FI5-6DSR|E*}?cbZtCk;!r_cXeaa^DA^rV* z0V_J3DK(khQFLt*0)N!&`uO_pRdRi?ik3OsXn#r}@Qdp0K64B2Zj2#4t>rKl5bV4=;qFOrIdNV{&eX-A!Ssmo%i+fE_Gwn<w%;ic79_s%76>6E2N zVdeu`GoK$-Kk|6oPp08;nINTiGX8oXgfKZFMr{=Wwhe#3opWLojH%QRsCH|}4~!4) z4zYq++W}>-Nf{Oeoz!Ay} zdJ?RI5Ohu+XF_|B5*%bj6KhpwLL*Cs6tOq;y`c6&=@CQ$SX0D&np z{ee=>eR?p%ED*^FmZmVGCVpuEY*|o)nh3SHgg7qo(V9gL*#@NL{qdTF%!eb#cbA3f z&82G8YlAVIzt~rEeUdi1YB!LEgs}~DFXfFG3h7Ti&CkPXx$&F&NK8&SI%xdJX~#(djMJxW62vn7!%=Q z^oONTr1t`bb{OzkmIs+`s2weQ%wC4$IL9XW4&=M@H|{0C_=JrkC4?wOez8Ny^=}Y< zml8hK!u3&RFC4{$PS}?`+_qupW=~(&o*8gj3WvqTtW24G`8epCk|^WD#=X~=jo_Q9)LC=oU$v)40fzNXNkjKRLR3o|ha&nt*_@3x(aeDn z3dqX81788%&a}+NYiR8lt{@pDwsNBafv!u|r3NpmtG^~G^J{Xd)5F27s-KU3W|(?5 zCpHgAzuul%{%N2e+L)9BN-8|tcQiPsS6YYe7?8qdICq!@P)=osN%{&j;ux@djWiHPii4h_{XbT(oh@%dHy#V7{ ze3-v7=$F~P`?zpdYI`(z*H;#FE}uYGG)%PSPFTox&)qmGgm_ghVQS5BuO-ldZMQv% z5L6QXa9H+Z(A~yW9?!7@${#RJ%)CSaZ!1yoD?=)xU zbw>G;{7gNB#0PlC1gPDaGkYC{_H_SocX21QHDqbx-#J%OIxxgDNa2Wq6_pi;%wG2* z7n6YuN(aHz4gm?>Ve!$I7a0C7ymtpnZ=1e2?@1nC*&aK)PS;M*-UHNMmj)t1?viF1 z?igqJiW!U>F;6OH7fnd@1iPvxpm?!-sd=`q-6S)<7<1s5y$*~&D`Rrx?jm2oBo~{v z+Wx4cuf`9a9r8e*Eg7zi)h|@{6}1pMUlLM$;-ZnV zL^VLXLrgMZopB-8sF95NteMM8BSE)xl@@6kVP`M^Ht5(xK=$pFT^Z&F{GKI&xWnT$ zT!V}J@4wZaRiNHKCV?kmF1rObzMnDEpy$k6nIsu+y(ck1dGP_2e0TeLuXwvP(UH>= z%{`gP44*&H8Z(Tl1sdXJASyjz=ygL0qWxFwws=ylY}% zukxBe{O2B*mi4HH`ubBzIZ%ahZiW!4UcwSA(U>x7YH$~K70%MRRkOpsRb;nf6+{+^ zg-MV}@Bup;6DzSf)cBw>1s@MviHSUS!Oz{_UFex~n$Y+twzo(?)x9v)i$Nn#$@q`r z)zC$-<|}0MW~_ zZ^iGpBri-Ok)$t7(wL+#3U8<4PWCDFN|XJi+EGz*QyT_7jj{}A*ctV6-&o+8jhs~B z-mYQc2ul;C`~9^nLhcE;B#YZg23{kUX%vy+B4hUI4M!xqw@EE3v+pCe<$V&J z#A-4;#jelaw0j~9g-15_&7R)wb1ne<(?T<%#Ov=Tx#D;7t11(8m7dop{3ca?WcqRA zD(}A-G5x-rlz2})oqFijjni~2b6q$iG*46S*YDnm$4qFN7ha&vKZ~KQ0HwJjJ#-mZ z#61S|vBOa0(SpbIz`>(!sm}*y^Ku|AlcibfOh~0n2w2el_w?rV1&6{k_EDXW!rrz8 zlq}+7)cW++NBdtm;1}Wcu)))Sk?UPe3{5v=3L`z{m#Mw`T!w3sX$}KS7W(69u>2D=z@Pm~-|;4F@57>H z0eAcvn#!>MMGiNA@`|6l@fGkRoIx{&JKl;bexwXtuTGp5vCkkP2OiR9Ahg^&yiykc zL4pryWXEr{y)&?uSfI|1{ZA+&ISY{Wo(0MjJPiHFD!%}*|H|YH-Rk>SCU{G6`wD(TLRBS;cwk)*uA{g=35*uz$SA|gLJ@bKLG*^jDMJ(<976hbh_jx_9 zb$otUnNth5KDRtrYLIzxTts>v_>JJrO~Rnl`96_!rQ2+wMhL|23R_B@<**pI;(Bcq z8FNjnBQll`Bcdm(UKUJ3*#PdV8>Gx|l$MHr;zQ$X#7(Z-iVJHr-Xu^h3nK7oF`w@b zrH?DIpn15tKkia-!nD`(dR6K8X8;7txVI_15SJEEwmb)aBJQ(qD*f=<^rQ?-{{B@y zHVIWF)9A-@5iZ5I8nR_8_DbtkJX2l3 zpV*tkXW{!=A@l;ys{80~Z36J}+ZS%*qd?k7e>6c|6ni}C-6!A@x>a6A`>Bt$=LLNM zaTBkxLta<7yYzSc;^l|fM#_d<8t(f0?TfsdIC{hRW%Ta74$})**6=p?g#>n=#WsF; zbaSxlS8U8Jd=*5((GG_l@H41&WTbdvNAB*oqb|?5ESgIlKSUF8wGb9kMA$vf93y>3uo}ljR6{viFwhU9kMrNks191QN6VNGWa^Ru@yV< z{F_}-&FT=Bp&uw2M7m7p!2!7^er4>Y1XYbM+b zGbBc^+8?m(szMb}$_W&-vXZa!xBB~#6nf)@{-S*`3AIUT;+E5KK(;Xsrd~1xTlUMt z3l@tPE%@z&S+SVK_u?ZuWr{^}^rj%uXljx#m1>Z?*NaEGRwuAb5|0>?-`sn>1~iPY zE{;*){^CM)yNwvO7G~ai)Yq;UVGC1u(BI9Jo?m0L| ziS{Sy37)`~Er9R$D%7u|m9|N878SQEu$nx%>yvDN*ChWN(V@VdkdDl)>Pi`+;ethM zxR2szC}{Eui~(_JCi`+H)79C6>5@ z3a&%+Bu2@El6D97<6~agP$uOALq{2(JdUS#fBFL4c99-CORug^?o??fau2J=A2ddj zE~b@0zwJWihO~*$8#4NWC!TcX!usyfQ|U5wM2^s8tIeHNB66(e?v#O#+1Zvb8I;?E#x(v%&Sf+vFs<===Ao}~ z3$?Ka&;Ef+s3+i4RA0|;+M5iab-FYaoPUpqcW~2ZC$RApG7=ibWe{ZrNoHkb*hBer zG(+bdw)}iFQ{-v7cQE?Y&O?4ubx|Z&cf}qgU!~Uo z*lpkpQZgsfxV5|-kvKh95k2fukoPVabswUpXZUp>Ko7&{Z8dm_p{jWAzxSH-GTLnA zXo=LG`D7#=L`=S&4YaXKC~R!Y}!)S*tP@IhI4cZ`|5&D5WpVEhj15$EV1Lg_wH zdb!4%pn*D{>VkSfy|$`(8YlXvdMk;BcQeHjp1T90a}T-`^AmBj_W*Ls z8y`+{e_`ydBSCY~w7$ZO*VK3rJ?$6%LaV(Ox2v?O2}1dTRvOpyn+?JR(Q9-k)~LZd zU2;Cv(}1tmhak6rZ|(*C1q|d(kkg=}gQ+BPPeIVdE_K95+x!KwV(^ z;7t5_V&m0oSb#qplu5>x^CtHzrppgReiYs!+!~q7+@VCRuunUv#Z_TUfD(*EMkIlV>=91gE3We9(oNPhDHOO+;SVj=`k;q`pD!3*DP~ z3M!ZNBE2}{kFL=H0^?gKh+%^xh5{r6aAod{v$GxndWVf$Jy|BUf@_o*IO+@CZtl^m zw_~fT{`K3r6k@b%-XhU!h@2}{h%aZqH0C{fwL=`37*K*OgivZWCn7l_o4pAvuZBHV zxJFG+WVtj4f~5#4_bD?N0%x_=>P?&nv{d9o2T(8Mma(_t&8&jmF z@k@x5%J?3KGD+wA_l*Rk!fr~{v}}OmFyhh3*g{Uci6fQ-*<;d%S@>?NL1!u4jAhU5 ze8RIu+B$CwsZ6EJ>q@Vgcja3>%KQRKJLIS>-CivavYad{!j|a8(Vom1F!PcQ|1-IL!h%iiVO|8mb3d+)8 zx`VPCLGtAn*%@s7N$uA&*sSa`cV8`%&cj-d;R{no8OtSEfW*1DusNhs(5}zdhtiGy z=3g(twBLly8!{&nZV(+zkG8eAK9V77otPZn<8E}9GAB~(roSzecA{q|fc3faLUGA= zRJYCsHRXH00sUI8n{{h#-@tBvNzh@)B85IzeBl6rtlEZK^JGzOj)ub`iu;KoX7-2H zG(lgj{tGe3->PSz_e|qR#TIfe<8LENBvbF@#+8GCejq~WzyLzsyAC)VFg$~AW}GpU zA^c?tR(rFSg1@yub<uqLBOr&bd?2by<$c>g@m{kxKdtOZx z;6XD+2Ck{DS*zg&OsnA>REu4EMl6_rCVh^+geGbKT{Pg#$4@!&AUf;gw=K6+pqH+Z zvzsyKOs2x9xQhBuiPU7#)aB}CKPo61C8AiXzq?5MY@&MoOAQ0taZp|=b<51kn-l10 z{!Ej@QFy}`{y-f)62?oe`A4oMSFpwVK-r7N=`gYs1VF!$8u{_olfr9yQR|7CvH2ZQ zK-pIR!9}gwGTnf$Ng?@I$16J)d1=W|=^)GQ3@wu3F9l6XX{P@C9HBxou1UQKszR%7 zd<|J=ssvNHC#1*n2RO)+|k5}jibp$v;Taz&<%|LegWMfRuDUH zv|0#Tj0omzKTZEC!G;Yo)X4t*V8&~!j0(!R!*F4<99Y|jVi~}w#e=#V>6!`snFQBB zq9jY}AF6)^c@P#WcFd@be*7+092xJnB}qL5q93jScP}NJA^#NISV%P6{8h)zl3F-J zdOH|P86C3D;cU(iBOit*e=6X6YdQ6A;SBH1!2gf5w}8rPX|_dif_or%2ol`g-Q9w_ zI|K<1!JXjluEE`1gS)#s!Fh}QpL^eZ=j?rV#&~0mbb!@geZ8uyyXNZdn#J)5`&LkN z1#mnT=Xg4VVn4usI!cBhO zRCEB#43gD~5<$smA`B0CTENt2>m;-K6@m+AqMJM}T#C8h&7^}v49)oCUbW(= z0v9j46O`d=_e7Ci@%qT0s3*2^qrBI_%~RU|kg`yPvqrqJ24>4eoGZKCNgJJUoa9+k z=9(8H!B-#6tn?=Lnnf6L->2d3}*{f^@Q%qh5qMe8q2${AR?KIO9IUk2_&M z$W>=jp*JJVBpyYzAsk{w7kiw8o~uUob&)20ST9=SO-Vq3!~Z)CCUu+S6*pKMrDR;j zJo8o&(!pB{8E3&w0m1p<(Kyt?)`b7jR9kZ=JFX(pgeX5QOUAj zr-5)OLsZXzjT}c|bRww7W;3L+g`kLe-gy&gS)tLG^%Mx57u}{~$*uIUC&#Oabg$Vw zwCmTcRR&5_dNk(B}_h#5Z|&seRw z-*r_$p2Uzzu;XSm`sywJx0t z?8F)GxlA5TU4pkwf?K_L;`g-#&vx7N$R|&JI8c#a8}>4THKF1r$r<~U^>k9tmAiiV za3sC@J5K*fx{zvx+OUX4+d=|PTnQbmBSkdZzut2D)e0PmjQb@idqs7Q%%*`Rjr^jt zmVaE%cKY6eX$&2(JPXwbgTGcuu#Msu3=N)s+Tnl!ANd4CC*BHp)OBckgX;3Neu$c( z&#-WDjgiI8$XYFu1;z4dVqA}!IFbm1)yU#f)TQhIq03x_A7IkZO!I7MZzY_{9C{2W zeY|(0o^)J_n{~{o*WRzcD!K^qOS|g4kZObeKAzl?z^2m*)%Zo;x^Y{8bXr$ds)h2G zwPnA~F*S;GQ}OkI-b9ncp-6ceZ{+BP%cpR&bb`@Z2ZN!J$*8jh9Ugw5u5Lfc`YA% zmDGW?D5-q)FIgC9J=C*Gy2C+E#nfb)+=;g0jcTebi9IaNd_S~^$%|937EnLX^E@M- z4@Qo6j<|s7W>e6ENNIPdYk}mW>hh-%5jrvT2Lx79jv+)A>AT~wFs$Hp-Endt``ebgo4t}m#4N(cmfeJ#nZ)5l#3 zKGdK_AORB=kbnuQ_`PnB4?2p2#-B-O1tbvuy@aJdlTb~vTlWub;QTWQ&47e|XhZX# zNvJ2;Jw$fEAcT3-7(YA&phRUjx*ooephoVuE&G3V zeM5HW1Zk8O_Dx(`Lv>&dYJ`n~c&kYW1qLV)sHsmV48*kIez+G0rB{VHk?=nK9?(~Q5Rq*g&N>e>lwO#D5{IS(#T3(3rwv55hvWE^g+tj1qt}vpzi$< zRz+aUqz&OOS?oIhB+Gj_pNM~CroLwxzef{N4D9V&k-qFA z{a?)Mzf2-o!`vFlyc~?mCmHC`cfKH4zHdEBD2BqUDw%k`J~+??I{?fA;IdHOoiRo4 zboCM!%j@#?oU-;PI#BoD=8Mn3d;$A5U-&9bIG`Ewx-e8# zg1Nqplo(LpW;UVn zwI*JA*i)%@I?%pzLl7*kBy&(GSrP1Tk@vJv=J?l|bbQtt(Ybqdb=S)**P4)Dz_{P6 z8xmjv<_D}>K8nKC8t%^|)L$>Z{|5;;eOEC8w6-G`%Rml#W1+*!DU4} zRrtn%5#|Dnu=KYPM)oOO2KbU^2fENmE^dU;JC6k$zL_)0dI)@<_#f>viC>_JkJdc z^&qd`{2>|O4+jB%=)y2*%2ee-FL#x>2l&IK5MplCwMhq!Uk(_$FmE;a(E&dI3HSja z{^I>c4z3UPYM^fxw>}60d>F8}^e`sua4K#1X|DZ7UGL>OBJpu6tAj?4zk8BDvrUwe zy*iotVQSN;H)pi{)(B*v5fDHlAowK)8b|7V-X@*Qf1Y&M>WUgF+oO{H18Yz)jkq`e zTGEyX7z@&3{3~PjMW{wc^%59$P zzD68?V@RRRK3FseN+MJE>WnNaA^B>`u9uZqy-pu>>^*@106UOTTh2SZ`SKoKTB6Sd zYe%Wg?d_IPk#_jV&ASco==NLl1r9+hJl)o5((}r5o~`ER5B<9z&``?nPN2IZXMvQ5&wR2x5kMG zd-`_?PIW!YEdL+@`p+Z)ZFv6=5-|Tr!fjoTCf+~zTIfIWwU2$~S=cwo3@!>d%V@w^+8XA{n-bgU6YlVj0M3#H14iH40)XcNe-F>=*8fO?8z2Dy z9)Ab$>;9|_CXypof`2c;>Cf8W3`qEgmkg&rYlDsC$jmZkZ13j!=T}FeNg)X z%Kk4NVg^7jH2>fse2<}JMc)5AcDSJiP{!Y5hm!7?=!}1Lmdms8=}Q6WB_NW2p^R(* zm41FhrLYRZ<5qyX{R0WNfCRvG|E+{SYr|N4ddWXHY$pJYj>Eoz%>Nr4wRV;qp8+1= z@8D?jx#70SzdHQ-`e_Hwtn{V8zkiUEKU2jEpo;JRAmPtcaRqcJ+~0So8{!|p$zKjP zyFeoVF#13HLuh;kjg;%pusMKUto{MYK`a1(lIq{l`Jo1Y!v7u_s|NlNt}UbHR{e(# z`4ijJzgeC=a00+J``c^V7y!c|0C3I!2Ck8F{Zfbjv&aHw{x5Iz%|B9>5dQJ4i$(ze zX#b84fYp)Pe^{CL*VU1J77WZ=OonQNaYh0wj?L^+(U$*3e(}>HK=dWIe9GHSE*+Z= z5m-Txvw<>9#`k2Vaxi?*3EIOcmvwg#$Pwm>e0pi^^B7!fKZ|V&fmZLJ^9Jo_f&XnV z^$CfzR%Ar7#^ZY{&P9K$drLcfStlO@MFsaZn1jz&d z>!F?AU%h;_lz?|b=Xrhzc}r)d1}D-}BYw1pM9}8Z+WvT}Y{Qy7`chx<`s>=O%SbsR zu2S+p?b~)x16IJ-iS|Oe7ZLDg?We~0U=tzf*5{2sj_GNAfk|(8;9?2fVyl=5!&TAe zx|>Gexv9a!&#-m=YV3d)*I0ozm3}|{{Zlc|lCI5vtr@axX==LlFmQYIf}S`)Py0U> z@nGn}zb%X|k9Y9crcJ#OS~Z(BOrI;T=M2ZDe}S3N7Aq`?Br8?5%4ja@tk==GSeo5d zvSGne?;FWkYfEQkDw{A*WgT$5F7#J3u*!@fcN>9oYB!7gV&I-GcQ%Kj$WpX6obcjsoj$fh5`z)+6Ct zGVm5VlpjpsSp>3q-}e3Sykw1epMcX_y9r}Ia1xHlL+8ZI&o#`$up&+>2X8G=JqK#i zOYcS1L)*1zT~*!~OTLf3_VxF_om?&(PhmB-G9HhhA?~F6FK#JJzx`vgPa=iJeB=OO ziOAm&mi*omr2OB6C3QRuN$RhThV}EWVf>~vo=t|cYj3B7Tk+KzKO&&gL5k3z;Z4d4 z$4Z%;PG9W1y9U{yS05ogg@Oh9sekPnVXR*o`4Y(3m#_|+GXA);`*NG$JmR9WtQp;0 zvZPZ%TQP7lm#Vikrlhf85WQDC|0EMAyUw*z z+0+4Tv)L+M?|mSc&}>WO_j{smbrm;TT6=!1T(l1e_XramY7yah(`zqR3!C)N$3O91 zsSF|=9d5pCOwNnmL+@hT)9Y=d4;nm9N;vOOorS{LcUY-%~v*Y+|Mw-b!t*d57jJ_Et6kAygSWy;O?lBjbG>ED?KtS&1`3~IG3?CHJoCJW;#^h ztsGKC5p(j*=s`OvUI;T}vcn0p&aAsg+48FNy}b?e-9V=9Hb2+6`JT3NoX=e}%DCzs zZjhwE%e{a4_b7DSC?9ZGQ0(q(nRof{cdRzy zrEcK^YkO)CGS0G{56&15gX2{||2^<}?F|p;t zc>P`6vEOEAxwhqX6Oezu<($9^4PD~8-Rrg7^0ee{QDw6&^8|VHW4;}c`y#`amO`XU zvxf1s`SzQC%ZZ<2Y3k1w^lGo*t316V@VPLN$&7^6C+)KK(7Y1sxU-H5g?Lg(HT5zA z0}D94rSx%da*R(#`Hq6jMFE)t*yXJnIWfQYo@iYiFx6B{I+M7s_V;aiaB$*qI>jo;$B&_pGB|74H=T$kgz_I-!>h1$WiYG z^mqw*!0iaN;d(yu%q4;!29Fnl`7i1#{FK-zUiFvbaF(|X3kDB^c>y;W6VVsF)`I4C zsOu)E+8SB7y0=~70g{z{)_-;Nyxsq{ZNgiD%l^1{rw`dZ$LRa1*26(zQLoxLwmhA* zoEZmiRVpo`VDaI;JJ3ew?5xdWW+~jb`t{_9m+3h}Es{9y!^Np}kH)A=Pcu34TnbUo zL6IbZ^tf|3>N5Kn=I2Y7jX8_8R_k{ol4q9Bpv{Z;SG}78+c0~Wd zb5_#9i|EXWHxoTYuBU;P51DpOZikbI+g}I1ih|o`g*)ZNwguBM)HLAg+%|I_5K>1%8tifcuR{_G5YZ1IPx(6{WO%R-udvNYuU6v&9N0#W;hi!Sy;^dPT4 zDZ|YoV@~GcYrF_64&n*ac9U)?PbAq|Jaa}Z!WVur(Rd#AY4r2h);=;gN_Uwz%u+pD z-Y^Ne^MXf5$s~D#1rG*DvHGA_BGPv4yfZ2JEeyA1rz$+WSp*rXz{$6jhxQotSM)7W3{9Xm65EAb`U(^XnY!8xvl)G(EtQ2d3{os=YgeXGlA zp<5~Eb#*jOr13HqzHWyS$Y1Bn=;zDvW*?1QExw2)h-N+ig#H>>)=Uel4vFOpsp+SgYLnCYBYdRyf;q)r_IpaU;p7ulNMSkhT}SClFi!rU7Vu zze_4VW@O{nM!bfh2n!w^TpkVTeET~~W>9RN6tMh##^=eQ2y) zHOU|dNYbE+trVFbZiD9gujZrXz94=7h~eOFl1y;_Y|3iuzLtcWRA)mu{HQRp=Wm44 zPoS7kNt+>WET|=sJrg`}xZR_KlCCuwh=SjGqsF_9J>z(dg{#!8Id!fh& zz5hVU?!SWJ5`XuXLNEOHU^vD_TzW8Ox2KPF^m_0B`Q3k`E3L>I4OIA_bfv%cqG2C1 z=--uf%eHgmn{wt9uguF%guA-4-cEhZ(SEk(0)8vI1OA%|r{-tXmM(l0JK4bO(zfY< z4>xkn=7#W3L4HASjz#_72;F>CB(PS|0%eMHS@P-j=H+xrwROdm<#Da;MR4ksyy{zs zKsmD_-)e-vrbWK*lYrlSASZ)v48EY-{yfifH(9#P9b+`7Hq_}}_*KB_uR1v!X66Xj z0);{ga=EjfobnS9kFshf7d(xAt_uwuSGV7czW8uy@oBQ~iS^H=GiTeWEsYJI(B5NU zM=}xS>n%=G2ghtaA+>@3CxKz`6|yCMgw^MqGw|0-T}t}DQva?=9dq_LBP^wGgh5iN z&%1m7j8?B&T{^|Nb+;)CTw9C&ozIQS>GinwdiDDJR(yIrdVL@OiWe^y`Rn|zraXyX z(K!L~JEt4^BxoJ$65EUd=fJU`){jSmHpg5`Ps#)%{Yf}q;(kHYB^hl@f*WMjdaA{< z8d!TY+*eb&O4?C=YEOR-YBSUoo-nUpLl<9ZN5BL{a{KI4+EWIX zX8YID&$$_oXE>_kzgsyn;^92Y^Zi%X78WTn3T*u*m@ za$ieHjenhBr01R*oMKG2{ZaH~yrwe=45_q8bbNauUneqsFy;iML9+h5BBM~|qB zCW23h+>4U*e)2|zcc;C`6=TQ=CNEL_XfC2BqFy8Z^Dd8QRHpNu0>&s|zg|Sdw#$Yl zMBc*tYyI{`O`9_6W$|tLak&vGktlUgC^L*mkV#wVwun*7woP-~snu_jTc>ib2%7EB zPuEJBxGZYwCdyfthBJ5#HB?3={OZYZ+82i&%X;UDus^haUbILLRcW}@L6=U%L(156 zdm6a}oBb{f#nJ6rIlHVa$Ky8klhA!tW7X9gQsv{T;UEStPju|(X*`>(?5dTMbzL9( zVaMT7s$&5;-^I=A`p|CUl9QRb+Uq($(!8~Tc$zb&X6O1imO92jhCus_OY$Nvj-)A* z@1w1plP1j$Q`KoaI445LoOup5U(*-PTcR09`+YM&rVbTB<>gH5qCmMu{NUgae<1gKrnQNJ;H#;c?2Ok*3mIL}KmH_|RRzB5Re$ z$!Z$3mVwn~QL2h4Blk#83dx4eVXwrXf!mR(EJa5^K> zWODN64EkkQArJR13Z17iSJAw+%UZ3~L(&pXc3oM^c{AIs<(BqZukvTvWwC5wpm=8x zd)h$aj()4oIk!WJDot*kCLIBRWZWXUAyz+5?xdR+XIaGg-Ou;#t}l%lc@nSIH9NjL zV^-LFIg1?8%an^3hUi?)4UZ>277G!>S!U*a7wzHn;pZn(B0nF*7$9smH3#$ zP3GE&ibj)5;W|;lc`^6ce}yw}tQYtvxyoL1!!!8kKfo9&F;7OCZzW@lrcYf(s!l9d z)FnZ64Bkh8L$Gh5ejVMaLpRzXQKb3~+E6_+Fn~MZK;^-&)xseM^X@1n`u?0x%X2OD zP=3Q7H>I-fH@UJ2nu=Yv+ugo>x$$Dk3=r@NImbj@ifZRn>Hpo(@wYDQCnw{1jmWtqi7-*HNzE|VTpq!klV z8?%#DBhg^B_dVD0`{H&93tk|5Qq>Z?e0^tbH*i%XUUM-JOFgXC9k?NgaLe{1=uYba z7b|ps`|FKP(x|xFN%x3CY6r##{t^6pj#HFsXk(-id`jYy44h8?6hn#L|$B!zifnCvDGU^^|^!bDB5@(l;_+TzK~ zO16>1eV>lUwXOf`KBftAZH3KFv#Ay#Ow+`5AMJV5AL+7xr18{-C-RH~NCQdM^lE73 zkk86OMQKU)$>Y2Ldg{i#lkvWd1xS$A9!G%5MK6_7P%hH^n(c{#$1Fl2Qfm*+06(4f z@#wHkL#E60jJ)9ZVPK~|2nu7ZqFMdk%!u+y{j47n%xA5XwMO-4#_BM{#djqw-T}0| zX4`v8*VynydA2)5ExALG6ssu((amB|*N_;er3(|KBMq_><5KKj<|386HmV3;=(uuD z*!UK_cXUH5aOfP<$XGxj>pfc3e{i`#5P9Fz|P$;Zvdb$mxx zohicq6E6@OGEt4LI_Nuu5-Fb%n7>q`P#la)*DF$y!nD5_8A*toSjOOx~4p_(&yPGE*S~2a}qkjk7AO< z7jb4Cx^)s0a>5_eajjx2gom|LIt;rFDNUs$FcMiJug& z4l+Zk4!ep5lL5RR3P_|JBr21u@@#f_v2_ND+GA5dN*U(TN*4X^nircvoz;_t>YGq) znc@9V3x~2>Mo)}WzRm8Svkyi)`r570It$9}(aW^M*wr+dp$W{~4B3{}NpA^fIum9d z`b!QezR?vi!&>;1d+7JG2L3iG%T;??Z$Ogl4uBly_R43lP=h$lXQ5 zgJhmzwa9gQg3N(U*2~)4W;pPr)ufJWQi5n zBJHQ@N_AbA`+Dx;{0vro>Rofrq4MOhfaa7YQ`bR6Z1>VT{;ZHx$nq+! z7|f*`^3W+=LyU-O91lbJHV=kUroCEqRJ?U z=al9%&oX2Lp&pYg+Yw1vSVPvs<%Z^<}FW=jDUJVtIomJ3!sj;(CZe3$~ol67U zW&wik!(6^AY(z#mD==iaLIkkgBWibk>!&c)B%K?i{CD5Xr$qZ%yU9vDw=+fca^3G^ zZJHl*(WqxxN%(3AKCer2LcFRs*&+y8Kw^+p36X3PZFy7=Ty@o&CIP33s3iX$vvlXLjc zeTd%2YJkNZcJ*Sqv!a2^xo07GbPE4 zcrM1K*yyGYf_t0_#AgsN51(Z+^1Z1pYa*h@N2^cF_K5#CaoHU9a%^mh#lBZVYrhbj zLM{ttJtk)3nCn)^4Wfh3vlcm$;~QaFLGHy0?;|xvg_WAbQbf44SW!xJWx(vAs&)Is zf{G;i>RC>Gb9Nk!lUfZ3YrFfcdlY14CVdqLYhGfLKtAk)scRcf-xVeo=3!S=>Nodx z_#2&b_MIIrMn%q#-~mabi_z5<@n#uE_Yz{{kYw#2vA2fx+$k7rD7(J``Ch2gV?qc% z2gc1Q3~bPu99WT9kvAVAyNK9PNfIG8h4uTpj%3$V>E!9;FDnHF68LL+sM>=m@+@4k zejuH#t|2=s7sJ(GWC-c5GosWM?N1{@e z^kfYz>8L|5+z%rOkmf5bhkXs50qDczu>ss4wT3_390XQs(SHy|Ix+?d$qsx3wL#w) zJ^jFqP}Bk9_#tZ0{vBrZUS5~}a*iK~byRK$vACwNupEh|xa3m(HydyIh~_a ztqNeiK6cEFS}MMywogMRHl)R zX7nR}SrD z?E91%)2VvTvI)CFl6HMxsoYwj5&?;X8jpBF)qDmLM~$Y!Z0pd`A~2Fe&0M#GJ*&JZh!o|bs`SzaC+qojZyICz{}hFOMPt&T6u9YrJ7>++WG@pj=fp9oIuog;Qk zxWsT|)%^vG=+^g*DaB%jxDGvjQ)`_FXdzW?zQyLX)^4{HckChGZOd;rI>WgSb&`#{f<-cVN49X9_y!??kZ%QBe{30)P3UnBxuSN5B@ zI>e_p;K=)A@8C?vMbKzlnV!>1nWE98k{n$bJPa%(xanRub0Y9Obh(Mor^T~xHzHoG zl-qp2oO;?iP9U3NyqBT%JjqOPVp*dbr6jQ_gXOm{CCe^(*qtr7FNnPR5&A4-wE@SQ z@{;JGufMo!$np`07FmGo^JamGXKY=Mn}-hLW#P>f%@}yHZ{K#IZ<~8qQkAY*Np7z` zy9*FbWXGZ-s_GNgOidAj%I4R6;Cy7=TQRH+OdRhxI{w8Q5UT}OgLqu!s$!a;yi8N% z;j9$QpzT||hglJcr%U0Y|VD;oDeMQtq_S85Yfrg&%o6xpmjvqjGyAu{!3_A;!G z=Pl}8@vxjalM$)4-ZX2s1syihH5kmx%?eliq!|5c)L;FX>yYr?vn`1a#%4bKxP*~` z_^bo9GptQJZ@`j7X*lstk|6<0fA}Lyq)=kuW_sCE(1HZ&D$_@-L}uqZ^g8%&0#n%P z0fWC6b+*C;uTdT=D#0tkCzpKQ@?Jr3QQx}hN}+}aw=MxGf~9n&wpmH(W&8`5>5n_& z@e)t!z-60H0A98)(eX1P*2)IoFs2z7qK!VKYDQ`K9K#x_mWELqsusQm43s0cWhqcz z4V23f2pXyets*aA+=PYZ5uMI~ zr4G;F4>4zI+1~d{hOvf|2&HzOmUB5Kp<*IN5^mN@>};B(j?4=3bmrDFevv1LX@v_D zPcqA8#S$H(P-f%QJ1a1D+8;cV;#3SWk!n=v(L#>cZHSU8mzoY)dD{A-2~;+lVX?RV zhYhLM(5eDU#kc%Dwjtu5Y@75Gq;#A1EpRz#ef6zrm0&Ns-2jKxTl8RTx_i&Ogc>H`p8uIrD6+Sh0b<1 z;6=SPH;(^~V+PATjSFJ%84m`UuxRLRN_gvx<2ZtSRLX|FOXiN?c%OD9vrWFI!&DC6 ziYeVl#k>wyIM_I_cEQr33z?Z_PEo-zY6NnP;7T60^WLJR==moJyPYZ`VtzWefXEH6qRi95##=lO|J* z`6hK_3{zPtzKE?Z9A8-v2)nc}J3JliM0uuYdkjc}gSnrPul ztm(kM^X6Q&nph2Ps>rdES=z!ZaK@8FED8HEf4@I6Q9L zw-jxq<lv;Jdxe;uq5(Vu>Ads%Z(bG)prfE5NL)UhDuvEeti)`$1I} z9HFDg74vWx_@Yc2t#(!~T;&`9>@lBy+_CLjXWIQzg}i$Quk1wc;GA#xk?>I>$9O!DXc16}?b{4j{3O>t##cBm2gIowtTG;>m1fyVB^*>C^Z z;8D{6D|ZuznUqEaX*%VDzCel!ScBHctnys$F+{{c%CtaaB6WZiuv>%3$APJiGm%io#M{>0<()NYpi{zb5c9@kwVRMw0t`di)QtE4Q~MqZ5!dpejk z`A}JxrE-|Oz>tPx16bs{k!UtT52FYCYr}hXdE+sS^kUEsWlznkX)ciR%dKRSXJ~W! zWe%yCA=+o69E1k2IrFWMB5cK*h@z%7afkK1LL%58G}%-IDqmiww1q7!r>x|28N6{u zXqB%F@t9P?4?i(VvU&!`@eQ5+;ve5w9i|VT>uBx&wPvv|*^dl@kO}&g+Pm*KVgawZ z`7(kVjAb2Gvm~4{{}Al@ny8~XjSqXTfRzVW@USqe=xp3d@`{k9wP8vBP|eRUY~U~L z@zbW;^C8h}%kY8m=pJ-_0w#y{m2{!Wx2vBHox#r`W0SA~L5_wFT$*3;7djK9^ze_y zj;W!G8r^Z7<3W*EtZ2+=-eD~bn5R>8NXffMEfc~WjyumA${75Yc<~Vb7N*DBXaG3QKJMu1{g5#elu%}3kTBY`H_;(f91|fH{qJhe2LIo z>>4TQ;@?`c<;^z)_)#J-aorhYA(zaN8rwEO=?pk(1N){^)BNWBn%j}PKEb>$^?kDH=RpYYust2RiR(`> ziW=6jKDF`sCd$*&+|U@}mR=~+*Xb&~EbY5h?b42rhQf#y0GxHZvV46#ZauPJs+(o? zq)hbOC$^#r<>2&4`7mdP-Og$E)Hmj7{Nl#(LBdy`1-#`*+!#}`y%EK$%D8j zQ2ehD_5QVsY|$K zqlCC&>3l3*n`!c$`SuE{R}k44JGfYG?-<0O)&h2Ta697@|6<-w+px%f6r4Vj>|0`D zLOoGE>a$)vd%~O`INJJo&Tbl%KnyE{{o;t1(PKnvWaQe=IG?syO`|^PKw<xW>r!h~AA4$jnxM+mh%-+nJMkQp=bhBw5;4kEPF@m7%R z8?4vnd=ZbETJM;Btaj{zLbuc+EL&@l>QvffgsoI(R-^8O%||aG7ccKV+l}}#s${*R z8lsbFC$Lq@5tz^bug;mk|580{cYHb{(XZ%8(-G-#XUV{=w%Dj#xlw{A%6DK#sVEz6&R^G+&Lqv&oNly8nTORo08h=7zUh-Q?Eqx@pCUwL#7NB9dtyq9wu=ExX}PfKZ$S zOk8_;1&78t%S0^9ka(i^^fLPMj21&a8mVOevet4Ml4w4UbCUIf)mNP4GmeUW_Aav4 zWsA~`i9YhY7tGs>zJwE@MfMdf493y&9n)^DClM#V=2T$?W6oughg@XNiCeO&3La~} zW~xK!qg}F;=PgeP_1_L;O9t*8p_!s~KXIiZ^{(kexYYgISDzhkNSvI-V7}kakC$;V z82_HuyE=q+#*!j?*!D8soyW(!$d^Pq8=#wB(WAt(o0r%F(WC6LqXtu5?4swX>Yqp3 z?aIi)D9%FtNKGUv>Q_^G#>{z=hvK|bOh-tvyHLJfOm~+zHE63mZT?^bQ{mWbB79oH zNp!`(f@_i2rN_~~-a(6j=zyLW4I6k61crLV!pN{ex0$rS%%NFYe{)2C*BHuy<{x*sSkn+Zo%QK`(elH@Z#gHH6;TJDFoPbi zqijlkSvXaz(Ap;V!HpvssBYAk{d?C?1w?X{MEa*)&ZR&w~1ug@L+QWiM^d21-v zk1S~wnG~wpI~0`yR|)!38OJ=zJ7vcvffNX>ENOuhB>~{(F1`xcO&(UwpzEZv%-aWn zXQAAOwYp5K6&Ge2RFE9fH!3cG=pM@D(aI8^jRC&GbrQo#-1JA>Br#esGhd7ny zMZ=%s)k0;h(cup-efd4m;lV29=n6#=KUd53g489bPcrM#!h4p{X`vxDcT`~HTlli# zSmw<`3qVq0eq<|$(n1mhx{CWvt)H~Ae2eT%(cCnp%c8H0>g1g~!hZ#FRJ3u~{2+V0 zCC)#WnJwn)LZmq!@BOM!jvQH8@VQ43G(uG?)*!f?66lnh+`rV>1zyuc;aGZGDy2On zIXzMYM)NbuyIk&xPu1@Q7fDM`(tlGmcQf#k1*0SH5DXel{H<4&)BdXQ*;DSRio&x{ z2so-(TtTS&Q9i9)>{d}0Fe-l4&z|Pwo^jXdLL^DBAj*y~esRJcO#*18Zw3K;x0LrU z2+0`;d6;}KzTP1);0}bA9hN)SSAS{bWZj}KevJGu*}{Se{HwNu3`So${N= z^~GPESggZ5j3zpB%Ukjv66LGVzV;={eh-Ad>I}m-qdnE4Hk6=zn!SV!UE9LFymD3- z#j&+ttwyY>>xL6o!d|@HD>`*=yZIVuu#CkhRy*eMDW1nD@!{@*JI&AI`R-yXjobXU z>xyT4vu=5&k7PT}#8JVKVx7cJbwEDzVz|>+_`a7MB=Bz+o5`+`byrE}vT*xp!ByhK znkVDbc|HG`r2$Gb_38k?^-5DN^~ts1`?`Ug~+}Lpl0_+#85L zEhS@R?8==g^V`Kom+;6A3= zH0fsN;r90F@PlHM^dtSll+9vR`&4v&Lk&Z0>9HI{Z&i$`VdR4D*Mx@Ox1YR1AQXXY zfuxr8HxDxvtTprfPQSTnW{Ao1c$kJyM&ROLlFaW?7o{u+HMvQWgDy8e2AG3C!f0S8 zM|Ulm*F(Ubo#ptC^coq~+D&PRSG^ zJk}9+p7=N6T)F0sRV}GIH2X~5w567h!>z3fQM~$Fi7fec+JCCFzoF_@mWL~wmNhTR zIJOvVRi9~Esor4{o{HW=loXo8cy2|1R99aS&&NfB=5rMJte9A+{wbDxLXkRl2)$%O zU%x&pC-1fcO<#t=w_YDy_FeOsn4Pj{Vw8L#sV1cZRF0!t$WJTtCEH{(6sg_=15i(* z)~)J`Q?p#<5C>G2Zq)=;l5!Y6KcXPydyJh|3@9j3!@3nWEwBjh94;odbukp&)|Q4o zj<0@S+uK@OqdvCSd|m2Xe3UCPz2TiAUicL0YUo@B@=|@&@^~621g&j_@5fZL2SY}s zHs?2os@1f_h7i3k?;EXS5z?Z5%X&$mbc(yWKoNL_5G`tSzlU>TT~Eyh8$^@A^WFhH zlX=Rr2Sei&5sA|X;y&NoeoxSO8_NgoFv!jN*G%g@nwO)yM7keb2P1=F<%C4p`v&M; zkd##2tI&-&aeJK*j6#i>_&NsHurPTX2oCHePBE?Q)Hs+r2%n)(QShIR3cz36@M6@1m5dt6NbI|(Jf7pd7`0rGM z1$`c-#E0M@9H!_mpI^sqj!>5FM>V{V7ah=oWGCj)yp+O}-wpY>@hjS<@8Vg-<#XFG zcO%X=jmvE7oODdXv;l2($`kqRgUy$ojWVWpXEq>D^zSH<4}bY* zO2!hJGm=ai(-hJ_*3;h$d?n45X4JHqAFd~RDao_zTPYtq9SfPZG0lDwI=0U`_^vPV zbKrIgC1PN_G%uz|@59u6Y~u7o4^3t88S-n;;7wo`{;$_%7rvwGE>Q-gqqLFe`{rgz z(xP;@j#1I0g>-AwzGlJ0(sk0In1O*@G!uudB8_EDp;ugar*Qj|`kt&B2tkx#S)EY{ z?4;W0@DZnhFm=sJ;xMJ{7sX$4OLj_<`E#@E`ww)QTe6Xp$AdH5{SzqRTVM@oAERXrkgKQjuVay_EN z>hNWPQE?^AKzLlrGim6Mh4DU*p=1fTF{k!+1J{gVw!X;Lx^`%8W&ideTY7MJIb-Ii zryMp(He`2NHQaX2<4g?j5{ z3@(y*kmRkO2f#foRDKhqAknO44Ch#VR(wpIipxk;%vjGeE0SMSjzy@Q%P#qx8nRpH z*hym0SLnY!B+Dl4HSHM`BfIfw771DS?ZSDw8ee0T1u-<$z!dG>>s!!*i;5-ay>++1thrQ70X<}{G(qEfTM*SjPfidMFsYwUj%3^fHS?bqzMHtD7tYZdQt2Qs3ZihPZT@ zhrt*s1IOzUo|PqcAhN*YeeZfeXOZ@L@pyp=2V;?F@E~b$y+k-Phjmm5I`Owmo#m4# zIG&$V!o(fAjOjkjXE?J1saNYC+ihDL&VF+LKUBQ~bR^LhsGXVE?3fcwY}>YN+qNc} z*tTsu6HaW~w)6Mg`~J7?TUo14byqb`rE8y!Z||LriEwt}+Hv0S=O>ltSf0{Gt^2wd zW+$qlwDJ*`)w|f|d#rDBi;%$Lk=7Z2c_%RRz|6Y_TFt0N{gBMmW;bWa`u289y5L*^;HKJ&EMblgco%t)qG16 z2-ro^&@dsrL$^P^3N+0ddcs$bSJ%UxFD|AJYqt#LXg8jb$tR>T(T>-Ti$@^CPN>TeWMQE0qvfJg3}j^&Gr@ zX7`9;XZOef$Qev1GchVDgH&yu!&Wyd@=-(pD?R<3NollolP}E@3we%hR4izpNwW}B z-yk1vB(Ah=G+sqM#CUM;)h9^{IKr4$uLEuyfLk>-5{3(?80tp)zm0=-drr#InnBIS zAeK%D9S@u-it7?&s7L#?b184N+Rl0Bf?%B#fouwoU++D;KPms(EP!@`)M#%Pxim8G zR=|6gMbspYAJ}d*bO?1-`wyF}a!BEvPx?9DMQHQUr?da8VMRT&<&w&-;rw~YX*EJ= zKFcXreEeK2ckrUAw>wh%w2czAzq|eka2w?IJ_%cW7HEdRizD@!2IvC#s5oJdvmeyR zsQfy-+S36MHg=X%SFRQA# zt9n|i$trhARwTJ{9QSb?4d1@bMRNL8hrt5#pp1*44zEi286L;C$)2{Qs#5^h}8u6N%6t3mqlO@c#nh1#-vx3$v zY0>6%DRH;_nUluObonu+RWh^Sj?3}d(UejZkGnvK_}$&B@W?BvV4RknI@jBdw)xVS zqD+T86!$32Kpz-tiE+%?c0(?#b9YizWwx~1jK13W+FCc6{lpxK6?9vM=@pJG=2MZr zUoD2wyjSzN^gB2C{*Ybcz?us;xUr5YKz7mTPw@1u&!QXbvAqscQFs=;JoZ2|oC zGJ3^GFlXYGIGv~?NbL+~%%xTQzIKW@=K2isXI_p?FOK(2mwm2?%&v-7(9O&PkGat- zFp@^$a7jRWcZoRrNhEqFI~Jmwe|j|0$C5Kgv}`JE-|CmeOM~g`1w4!-iv6p4g><`y zi9deVZ^v)}O`$Ri97?^*gE-!HO&PR4jsJjV=A>HRaLr zlsz^@=Hy8u%?McDMYn6WD$hubIt!VoHYwT^592f31d7G}qQx{m{qy{bUjj^f($JyOdoAz4F;hmV)>8GQtb>c11V8a<#A7W~q z-O-&peZT~DNY*}VNB{UaQi(UN2K^lq0@cm<2^zYAYx#H&p`&mj+q#E03-l0F z7_DCeLRif->aXCv>frY($gTfvr^Lt4zaIhk{&L|Y!^lWEY z%&NOtY8F8(?lcs-f02_AK&X-yK+rH*vI^(jv?&Vb<;M*rgK=5rL)gnzyt;mPa)c5< z)*v236xabTl?7Mp=&!iosfqY5?sy!qt=Y38_hRfdeMt+%y+F|a1mugC{yh-1swh&& z%^phBIRE_HwLcPtAr&s^bWSlinlSB@pqAe1r`eh|sTXxA!V+lo~G^l6M|*fHc0!l;O(5Qdche}38-lcJ^re#7OD_<)~1$1kUx=&rqJRl z`P>_z`}9utdf|ekF{>i2%UNL^jn%Al4)PxhZ)zAUsgcZQ|x z3ykr9p}FJ>EM-2+lEH!>E8+VXJDP_rRplc_^EU(PM@b+8+7*CL&ZYxvP{;5xN@xt; z2P{*?Su>`Y4n}JcYR#Z`{$Tl{zJHn$AyPXNvQXEO3<;37MURsrozG#^hKp=!9+?4j zcr?8r+$&`8);7 zTW-wieSk^_t1+n0d>-Qb@6#DbLpg`~zSMZC75#;3@}b8D%a(Qx;19pqkC5|G94@OD znEJ5{`@KT(he;L6t+BbgZLBc=-5oBN3OkaWA6l4%)tFFbw_q?G9X>!(N8>&YmOF%| znfi4EJUfurWJZkk8m;*jG(qN%IrDL|Vl2F6;i+hWY|EUKzz70V83a+@L5id-n6*Fe z^bY}oX*0c7{_z^ZmD~e0Nsi#;n(OeJw&&xLEPduU<;SMz+HCoBN{d`q*;!S}N{eY3 zrEnZ=7zbFv{!&E^$9_G``@Ukl`)@vvMTk+901})i$|OaEyaTnV(pjl%w0Pym9S$vq zZt$$6d?&KzZimvd;l*Xt-T!k}rS$rJj{e0isA(Sd)m`cQB*3Zs&&rmUVbFrH)yC7~ ze#*6#@NNCl3bEWLSMW14eMa33H)|5~BYN*AC37b^>k6sLu zsE-&;e7cQF#Frjn6|#WYv4VSyfpPKWVIRt^flvyuRmO3U{LX?v%`(ceYtJg#^Z{KN z(C_8HK}JQo)`VPtfzq8YW~=F2frGj%HAj~_^iF|uPp;yBKl_P|?ysr%VJj8IBw^>li9=jR zGbT4v+}vkC*0eC0L7bYQakF&CKN}yk*TzLsg;-T@ zjSiZ0gvBWNuHF_+A}S~r0!5y{0sHgr;lA})Y6dXFXmX>2c(0Jo>lki}{MT8(e)OOx zq+J2sXa9CfaDzOO*YU+pf%&A@SZJm&C;?t1!BVQuvUODOcU;gnlzr7-ydqjMv8_$f z-jJ`QG6d=}mO`x4VtB9o8>RR@gpX)HaVp8$;^9>jA`~kVFP6v8&J4YO<#v|RnB;Z# zs(x?B54_?hXgUGalCT+pcr6toD8*SQKpfN!HxBwW+BXWJB_Tr5++79J{%r5)HM*9x zky&IL;&joW)jxepY|wMmfYpXQP@az>oqMSKi?_CXKB2m{9GA&QU!@Fwg`dFX7}Q1R z;DV!)67nYww>$z+3aC&@)+sg{wftOaX*p6G(O2RyE(G))6-!w6tj~bTsUD(i zz7reAqgSZD4~?Rhz!I?)Hp_Ag7T&R@O$Krp1T`K~?<E=B+1)X*cC5N43x!)IQ zu(@+!|B#eH6;5EZsZJp6K3O*nr| z-+(SaXWt!CPsY!Ca`+-zXxT`$O`m2)U00{78=Dt98=i(Aji`EZEtn)N-3+G( z`AB-B%C#8p);aHIABVcv1DELDv|(3Lq<(r`-h_Y zz~iqKyr7u`Q8gwDnQVLj?^X?|#O{(YsqxtpOex9`fGY}ta} zgj`cs#aEZFK-!rut0lEkU)n1&{j}C`UCgsL9#exQV?EbMu#)>rZ&?htot)d@&G7;? z(oJoi-<6^BO;Mk{)o0~eZ||-jf4f;96Zw?5w3hJSuY^WCJcKz14xUV{y>mDIP-;Pc zDJEZP7!rJ@zU5`YG4H8`LE^8+Q~PkrRT~a94Ka`~dVTS#6bq^p=sNNuUgWkygjJ-O2{)vIL9Xr0|9*`^3A`&8K)2WRfOly*r2oIg zq1qE9kPbnb73=6mpd~5LS{@QmCpS1-H+ONbh*S?MSS}!L{!$c=TBn$c*eE^?dB2jv zJAF$f&T9VhAIVN--NlDN03fX`Dy*(?X%v7lbQ3t=4X!eilF*7n0VNA*1Sg6lA+e?$ z8&_IZJ{2c8Um4Gj(e@>r7PEQnEmjn$?<-cMI6%_$eXyqdh++k>N^jiSnibcjs!gTM zmEH}t{qcO1&W?S{GdK6j=Ha1-(F6Sx^LCWG%O}LtW|U$y(17=}`dB|E{CTr|arKaP z@wtx@$#Tnm4tR^7LhRGxg z6OX3(npihG9CLL-f_pq1LvVGj(6My(__m=-q7(>0`@tYwlVdyShLCkg&S7P)S+HTA z1D)$$;KyL&gS;k|^%0PCri?+4$6f5e>V_Ff`{Ss^GyrokIA#KoF^}v)NED8*bkNCp zJZmNDT0#1J{XQyfv_R%VbseHD-CFO#WMS8Y6G713WvNLF!sy{<^`}M;d5k5z-s6^u zWqQ{t$k{{*e>8Qze*f@OGD6V|(Ze8}q1%Sn+sv*3KkDAxdfrwy?exZUHZ*OsFvePb zBpzStLQ0=im8vJ}%h+xW4$scS>&VRLd~MW;H#YcBrhAus@f|{y73D9dy#U>oHT=rI z(i7?AvIWSjblGe6ai)9*I6_QgCuu5Cl&8Vi`_rAb;O9oA>(-j)p@)KX z96DcfUuS{ohgusNr#TE4!LLPj7C^X+JeHwG4CV)4oV6{Refwt0+=IssPMdgScdbnQ zh_`pUk4rAF+aX5N^go~g;CpdiN$l-P*t%*1OKZ7Nd~9W7!$C2#?X;F3rX*T(+*5?9 zvTyP|Zsba9qJ>=z5p1GsT)lS(3T9smRT;~%_lfg2#?gi_zqh{dbck}8OlkW5r%V8bDS_`A)s6LX>U z5`o6k1N0hhg8_Ux3$Z%Nah{a=D-qvVEI~(B z^eIT|gHRN=_Hl&qZ??#S%#~#R{jYpgMHCkCp@=|d3IJ+zVQfU-+S{w|#Yrc4o%Z7< z(yWw?CT)>gpakkHY(FUQk6728BvYJ%lshqa$YD9S7JM}kRE+962?cr?ULY?(5H!S8 zC$G+xlKI_C?R;*dLi-}VV#B-X#I|Q~XQ5eb%hG&mE(8iH^egpPv^rc-xA!-<8{2L7 zwq+Df+aj7a50@42ztbLPwV~_8q0Ih^fV}$@bEA7aea*=EnAXbnK)Xo<2IbJz$u?#N zx}&l!$*~6gl8>P!!-?vMon}lcsBI$?cxw2+Q!}%?ej&qL8`Jz5Tjl}kL*A_ZNeV@c z7ArPXOOcx8^S8J`V_6#KhM%j;_qSQzE1)7%9x`f7LJ!}oc0NDWjT1_}?4F;3>IA^% zrNH)Greg_WmoAE5$^~BP*P2;U$2;jHXg6a$hDNw&vUN9nD>lZ_D1GQp{7j!#H?%GK zyZBVGE14-93>;n^*Rg*X#r9&?FJa%Bor%qiRoN~rT$;R^kaWBOJLJw@!q-OO4l_E^ z6WsvKbd#@N>a;F@o|54Pq#@pWxT!*#QQS9IxIh+S7B<=Z>)v}RZ}P_(P`Bi{sz-Qy)ILdFVsO5)H(S=zl@ zD6B=_vbu9>scM>>M1QkTcW-;0Pg4M9eZdaU!gZ{?>RLwsS=7*LmUpsg$i#yK zl`8S|`on~GOxD((cyn&144??hP`(H(hvc~1Gwy4*hgxaxft?pHVojV?h%{Ay#u_31 z+;IHhPaQN6{ylx9uLi|%O zjKwE^aG(sBfl|oFY|f)RET{bR4R*YlF5kV92O#EAeuB#&UqY$tA^Zt($g}kVX!J=o z4olu+p#K=`xQKGoI=iqOsHnNlZEYqer=2`HK_;^Lg{UE961wLUAnJ^rKUdD)Qaa&J z-$*%0(?5+Asyfsrf{EQf{a%6`noLS$h~yI7X!cd|NVXe{EpZAc8v@E+bqm`*8 z^aeNDA0tspYG50JI+CNrbb2w7N9%%r>_+viwl35NIysUE(GKBi>GP8_ZLjoxbk`EZ zzYCwkmcJ|LSeWB#0t{qYt0H2udN9k>nRBWA#uSLpeFVu7B?d^A)ge|oqtqgQjG z5gRORil0QbiR*rnP@76}X9Ry*0+Ax654l?;3ZE|9mJN7YGIyKeb%!ztcYRj;1`nIG z`k-cMh&UxhCG5Yt+A?8oJ>u^@8u-2T;p6JjH@dOsUymDJyBzI9BbW4#+PwJdWSmO; z%Uq!>j7LUepEfU5J>EjqQ+A^pZ+B;F8Njx3BZ=+RpW(cbFOPw5D{9LGour?+6>=-) z4|KwAA3Yc`D}989Uc*9>*{z99^aRn;K9{rVO|)zxw`)tv)w12t?z6J)+{XRtcFYP>$Le}?Ye`f*t21~A_rP1SdS3t)TMOwH<-kI*CyzF3{e ze}R-9LAhMW%hSQddazVZ#9!~k^PJGP*8eV*I%E=6EWgH%>+S$-7e0FQO7;sFU?~`2 zjYjfFYO3|(t9!zzdyXxvZ*D?-Esx^tkp6KB?n0|W^DtyK57J)G?Bwp@^854U;Cn;Y z??3qI^78r7@g&Fb7IhNbbjWlZ2;S{;!KV2x`TxZ7Wn|tSANVxiT6_YC1a1Yx$}$tX zTI;W%GW>q(TS=t7T5Cb?2>ZGDJbiB90JCu3U*p$xyT6_mhDbg9UcPv>H_=H$!G%_m zTiz3QD`zYkIkm#9*n9?E{JdaZRFp=p+E%N5Q%Ad%&ny|)@B-!78$=boewH-iRN1U_ zW+>s?TuW?fO>pHT8(n78QOnfjHuNp6U^V^Gerl{j;)ynkIxN0K@?mBA9p^V#ews~k zkQmm5(GVV7#aJDOotRUJqlpH&&F~1}g7qcuB#nE@H_X>haAz&YriM@JJx6$X z^B5J{<$D;}!n{lGOF8(PPAM{&$*482kji&&aIi#HIw+ip^?+d`fq-d7jCk#)EzO|r zc}BV!mXHs&99PN5nSkpf@p9xwcNZt-iTG)e z1qa;n6t1CXs^*mkaPw%bNK6gf7WnH0?7U5+J8S*AyDEmu5r$Bl$JC&75+}v#e(=&c z>FGViGE%7!uDo%rvjM%QpBPJAqwT+LYpVc7^UpZ|p1W@R+Um7x^lnAXKAp4D%l5~S zX`VlL-RX%U67b~mo#N(5-4un<1BKH(8SV)N3lD#vtbonHosDa&tM1ygXhi*H?C!Bw znfm>{+caz)voY@i4g3?KcUU!i%FP~j>P%>h&;H(=+MaXe%E5Bd8n7%QnZuk?&&RMy<3fRQTgK}XzfY$ z$kkBg=s*ks1sX{2Z+=sgYcqADYGb8;p1r3g!D`pkNQwh}ZT4+D!iH1Hu=cK~kRw-+ zN>BMK8X?6J{k9F5>^+>7V}oC^%eKR6hb_Bcqw;Pmc&-M98O0yR zS8Irk2@`>(7|>GQbzN}937W*K;wy9hFjpr8PGd111E5Xjkq^|NmR3`cZ%ssN&6)xJ za8D*eLGVg@?pMzpTwhnTUtYD|Ke;3AM}eX93Mv{V+m*o9;mjv%Za7D;@lbY300YVR zwl*v}{pbk_nxOe}U2U(ZPHmkk&Dd-Sqs!?ByE%V;a;&=fx0_b+E=7QW&Y)z`_j}cu z0*R!bf6DW*@$7Vc329w)x+B{?!%YN;(l@b`PUEd!#W&ZKHsXuQ`(lFOuV5`G@ZINU zgp*;Z`B*|*8<#Cd(Tsa<3vltKhK-1oh1AYH)I-toFYw1>Q`;r!gsLD^^NfUA8}CoY z5)B3@3-R&%eBP3ynuC#5v&X8rr6MT1RvU3>Dp|!sEiEV(k}0Ia7eqNYKl5XFbCwgJ zZ&JOT0tXx`xnLArV_c4wGM-w9bk-zmxT{1lsHWm}GK&kSFJHkG;Tc0M!(EaN=|Z%`O?L;d>)*DF zZjy^Q%2(6pkK2AEQf1eRaXn=J0PMJqnD;zQuwA{_s--vdb8@uesiQfIOIJd)ELUDu z{*qs+?)fe!FO9p?>XVeIVN}=>|JK5tVY$$ts~8yG+kj4QJe>QF$yOk?8tJ7L`MO_q ztu>B8?HhAPs^!Y58H*e465E8QyKHxeVk!22Ei~>fz}Z-;gTR{FlDlD2PS4wakSx&u zMY7gn_64SUi}*s1ALarRmqf7dk&@5(Ug=|F0_#B-Hov9Crn4;v59~_Rm^qo5c0^J; z?#@8X4bt2(dm7X)kdxkDD$fKy)|(P>ttXnK5xb>X{_ScZXnS9)yqvXQZ6sXl;ALK- zQ}dH`zaaS1TYY>lTt)ixjTr6o{HM30xu`^Aho)NY=sT}wWn2{FJoH0Gp2tCC?6CdG z#=KwXq2UV8|5!#^?h#p^nF{rx;auX|{X$Vxjn~;Z^>1m2eM$(9lTLi=IP{ej zSGw7^nZ{#M-nm4G2U`^7O!<3Ah&ntT_oNCHkEV>8=D#~rOv}p+l0{3T8N)*W(#vM+ zk2)h=9DUrXIa%qz6=0=QN56&_0g>~ak8e)w3`iWANq&aY*o`5g57F0_uVx))U9NSm zFEEw`KnB<2k_`OfB7r%gbSzUCA!dLd*_@L;-Isw|0kFBtIs*!pKcc_u5}q1cH+08> zj3_i|nxlV%4@8= zpG_#-e@}_DKi1Bra;}co-kw9b`ny5eR;Lq$)8uZw_}j>f6$ioN_VDnKB295=fp4bh zjWCh^fg%6X5I(P(Q|AEP>bl}IlI0oT9D-7uisJfq$#a9dVOZec-p_5W1^5oyNHYys zRdqQoe=UdmHy?Tr;CCgU9i3qPJ%e$quM!w0T@4s91$ub1#Jk`xK7rx!L=gh@V6>k| zODxV}If^k4p%Z3C8wK>BDu8eD0;ggGrG%DJ@}-0i1&GSADA4zR5MXz1gQNb0wXY%Y z3HY=>*08Z{b#HF?zO7oaX?{EcYv`VQ+-jA13=pcT=sgpvFR0@7@ljrN_3>HGK}JY~ zgS7*dsgXC7}gfy>_9657yOPLZ982QI~q79*8cf?3;dVdYCKl-lDJ_Z8a z^x-yXdaVcH@Ne0g!K2&Ht41AX+0ds~*M17RihpZIjJr;?GCoA*+Kt;+B=S23fpUiC zrlM-&?EBY>%D!z=rWJb>u4QjHsR}PV9Yh9m<&rW1lP;8%oyMKTb*uqz>J0J4P*+8W zvTewgX7{$5_a5Wn(N$ygAqJqs4A0o+7e+iQfza9~_d?cGOZKHbg+UaSQuBu>wa*y+ z+s&RAC-mFv&E7DV*Zk!}`-iU^Qh3S#PqW^5qX3rXnmrDN{*EIK7FCbS`KL|Sau2)- z3O^7r?vPfLclI%4s{KcVCN87qd=vSIG8s#19_;sTeB3n`h!db?i&(eCgQF27!{dENXaq^$yGlr&HpF7fVt3P$EY6p>-^GpSYFL6 zbB6|2DtSH)gAz5a3RhsIr8zb?Ce&>zo4)KJ{3B?mN#woX{t};?EIT^5KcmW3Dwq0F z&;9P6A>}k7pR@fyE$5sKQi{~`;8Y{Dq947{^cCGO8_-k{UJcA67~jE=KT#Ae2V^zV z!?#TM?*s(%q$MtH$$Iozsf&KjBQsrOZ@KvQ)^=0c05(DYC3WLw z;UFoI{Pf>Rg@FcWjX!SG@ej8} zAJ~Q6#+mpAT#H16ITv z`z0rvi);M`kaTCX{}_-N2EHiWaMdg3|JJddY1|4ni(hF9mWFKk;UuEcr97$VUY02$ zXu2jv+DWRa@MD8SaUb8PQyI5BhI@}lUVhov)7Eq$w{Qd_kE4%HWV(Urvi z$C_O`3nTx#CebQ&=lkQ*l}$dPbVLaEoDm@D>0!|?UdlL$_yjHnAFTM>XPz+Jk}7$ut>L~GSo4=&iqrHYPy@J|>^w31t-&9-dy-lNZ~AX{mLZZJ3}WIt@PRc` zB*g!DPD&|MQHaq@$w=P|yv1K@))6+UW*gmJ zO4Byr0kHnvR$`onz9&$tm&T$E{87ywww08oMI1}Nk7hgBXg`^W9yS$xB0gFJf_-&h zM%S|wOw0>9&Gz~Kym|1gs<`2B$(C^=5@~Fu)XHpUz22o>lk-=_E-zfNksyU41@tnt zVB6q?z9~IZD%OOw0aH*DG?UV5bkWbW?A`5Qd}nm%$qYYKvY z>rtfTxGa;48gwq~U}uG;>>;#bdy`2FU~j)^W{#3Ve7P_LE`p3C>A~9B)?~lGB(^@a zTf`ITs5YlB7hCYPPc>B27Cq>8;fvg@c(-p=9?Zn(rFL4}qNN)&qSxFXI4*3^tu)D8 z0yz(}D(Pa*s=NG>$He!$r!SPR9360ToC{Zi6cg|v$Pon{UbasXk0Koh94nFcc+2OT zRX-rtafa)yGUIKm-eeu)^BTi(rYTR9;P(ouWmq-!Z;dn1c|4?TYbR+|TAWtn(wJZt z7Fuf4*F|{ees^jD6_Md*07aEP!_T7i$ERz(&Wyoq+8AA5myq&D%0M~K#T7ui8 zi}!#NhoMl$&zi;cOQdeZ(xUbeHoK7L0J0$P|opYaQ||p zzvO{RDN0f{R&G7?7;Z5lS>nE;vF6fZnc|9D5hX!EXPGMKB#b$+%0@k9kIEC{Oc29b zX`OgIqUw@Xg7rCYu$6IGT#SLGtRB&m>p&Um`=Oz!%Jx=)ta%Gac z6sBfw3-`^fmY!O59m8CYf5J7Nq>ilpsn=Kt~-l}8SD>pq!?RdO{^t9w{7u+mnkf`@>$I`OU1}88_e7 z4&0*!ZE-Y+M=|B^hJhV;f;EFg*^qI?2uYLPcA`>cZ?@DUH4BChV5PzJbZY_VFt%VX zSXZXqjta65UB>&l3|Y51!ItUSOU*D5udfNwz&~1!>PF5sC&`c+pGc*&@OpIhRXr-0 z#)|U()vGEts#+_nzXSFwXrON=g7&SpR@@r935~e?(yWf{($g8shkwwB1akWRse&O!^RiO|L9a{tl*mUQcoxT zC+&aIU&vDSz2T3!Mf4vYCvGwO7WSH|%3MxHOd}O@L$Bq#fjWXr*zfghH@^!T=%0KY zuRj2=X|Ap+(Qc2#A+Cd5R&nxc(QXKK;R}W0d=awC1V+1AL5WCMX{DvLhxB|R5yvK< zWPYo5p%&gxRu}HTu8PCFoyf&%L?#W(f}u;3 zU5^X;^XnYLn30jB#VAt;Ij9AZS?XzGG_#NC;T>Td%ipE(C}hD2V<>52Y;8p}<2XOO zX8klLLUCKcZ6gP55P<_#*cz=p?7Ava3*I(*YZamG8gPBl5?F8c*V=9lY+d;8U^BMu zig*Qyi$1?yn>*jx$4>1Z%YDC#a0c+#lGyI|2H#diX|2`!)|v!H3#SfZOBw(Ri~jGB zWLhnVHpo+NFAu0~z#7c1t3NR)E>_|2_&1nxm8X&1v0O?eC>DS=r-0ftz!_ZU{~gAQ zsibKr^GL6-VGP2H31r8ZO9|_wLn>!-E)x8@Qjqwyt{lAUkU14i=3?0or)P`J%^Q`_ z?DzTFRKm5KC;V)7GdovL=S*)}Crts(&y+|Sh&qm?$SrnP@-Vb(Z!D#`A&T~8Xy}Q7 zN_Znl^3DGv-*3}pBKyTq*O)KFo;(&sgl>M=kv_9>Tkxv5ExNb(8r+KRrJ)U|v+3fE zEd_os%B{&iM{>GuM0_L#fL>6%0B<4EPreQ>!yj@=<9m_9p}cgX1#}Y z-Mmntsb86g)KB)Wc~)8-ozhW&?^7U&_m~GTd*Ew%_FJHF%kV zdQ>e%Z&z!Q-1PRE~y@ z(H%8Z$7WoiVXc6Pn(lm(jgK^K+%i)o;HTxzFTWw9bSxU2m(f)Bw|#0v!RS=60u7>67#H&$gl>aJNlNbQjP$GsQMhTWyy26&%H8 zkBG^;duXMnmmamzhT5vr%Mtn?ca$w$nOc{pTUyOa=gDdedEkp1IvXn`kQwwGKGeNu zvW+*Z<7c*fOXbXVOAAfq(iV*de_|^cM%|pkwO}VT&;{4G z^L!!*7X#wPpzr9Kq6kx^4{p~^Oa!Z`OwHe9QJ(bgKd^XKjhK9(^0~H z5v%1?kmpFwJrb{w8WjheOVV@{^I7r@hSyvpTe+FTk^o2+>LkkjK0j;x=^R@miW#^f zHW2lr1{vd)7!59T$qv=YYNhqlmdmC!<;^1#mG3s2EUME zun15%8pQnaGG9DO0U2>2S10K0BaqH5t`ye5Af5ne0dwOD@$Urzmx~t#L|E@#fcvM% z%q3?QF15D_#LON)KDHI_(@mVur0oVT>kq9US3Yn$X9u+0=6$ph&Ffz%g_`b9hqrqf z6=!}Hn&$drv{os!bs67wtpwFGoAXeclLdL1q$9>?Z4B!nrOSVhoad9w^Fs99E+_EYbB%D5&bJ*wQYNmLe#IPutqraRIXO_1 zR{fe?pI;4JJLo8Dg2*~ZZ@McVd7-{sNd~r-XFI0hO7AI1T}1m^zMI@OP@u80;I5+k znUS$E615gH_p{sw1;BP~eS6(Fku`;{4wkvQQ#iQ@K2nD6=!h!Jjdc?gMUTB=9jZO` z5LvCBxQvjtiU24aCrf!f_C0%51)Xu>^Joxp2GS{^lUtZHa+KJ?ZtiI_X%QKwSBMl? zO2zQ9@R1u>zBj`UUAzq&ITOnbP20R_nDg56_^FuDXCXz<=cUGduT~va$o>V<5e2;3 zp(=FRF?Yi9<|dp>ScD(DkZ=OTmfX`0LE19kyKgSBE+E#<_b}$vYknC(MZ)vm@ew~e zg6JE}MJ+_hsov)bm9!f;=*82=ctW|Ao#OC!o`(H;{I-vlxNoO|PnKR_JYkz(Zp1I& zgaoz%x=-#+Sig${(9mJV)CS3JY!XLBNj{7L*fwm2!qC^j{wJYcni})?pX2TO=<_J* zaXG7wN&a+i&FP#9S@7?i&%o-3mD3@VRlaG+A|S4Oyjo6JD1Ed8|{cRZRrfeZr2X>~>id7m$Xm=8c#|R~h2eaeL+Gqvelz zJ^S3>)f9xW>-t$E7I39pLM6ShFdgGW%z3{T|FE~~ynT~-8w}-JNZcVhypDM>4f)3O zRwB|Rw)P^eJ%>4i>Lx1oXAl#awbHAY9;ZNF<&bFjJpKaH??nx1Qyp~~V582#CS%A% z%^^@Lj#PCfpTf!Aia}n^9g)bi2f_gmkfpdiO0Kag(O$3B>!%RU28L02e&;W0hG|wn z$KUdgbKE@YDgCy^?fgfdmq)R8s0KlR=urZQm)M_cCHKeku|JDsr=zwLv zdjtPO3^h~~ns2`Cjf8&bImCZquAIF)^jbNCHReLcwXHfH)IJ-is-7&{dR#W|>>#aM zAR)~xNRxs+WL#)x`k6--y|KBCQxQ$?#l0M^Eb}m$|KVrX33g7RZ!cU`1urjIR~k7Q zYdaw%hLKX0E*``J;Y~3FTXPc2OECm|n=1vbHA@#yURhycE#vtiArFK6nuWA{7`Z1r zCi1Qna*`IU*|xvgrT^r;uopnlK_OdtBL7#5mIIP?^*Jn@zg69g0H@5WGQX9ou_3cxvdd?eH7$0d{|WA!4w)k-q+6ov4Spk9 zgB%(}I@~pB7`c}(Ha(@)8a@|`bb2)|Vihj8ee1Oy7MW$|Bg)Rau|Z*uVI2u zyfC7Z4;f=+fm*{$wlHDdBw`Emwlu-+Gf`w8TpDKl5<=|$?MA6@p#e@!geFW<`aZ*_ zPemaB`X=F{v|BymDpK=-%8j;|;;SCeVOfXK>_a}6=Zn`O3R^EbM01A36#S zJC;JwY}FKMPTMG`lUfQCpgT`XcNB%g-CksmNc)mig8Pt_gKywvR!OUVQ^^TwRrN-7 za$i^VWm(Z}!ASa*{o?xzn~&n?>p1azloDQCpAuh5Oh4wEV>#9DLQ8dzNvn3w2byNE z2EVPIoDAz`=PURxbNVnI{RIR~5oTZLCN7g`nbrvK*F+(LGDZ=z5hi7HpTb-4EFwMm zEVK%B!8a}m`F7q!*$Q+EGx1p+V5ZC9lGU zq?@ppVnKl500FWC$1p0FsmCxuxXK)*jw*-SWju!mc0rvuwL^GBnT}QI2;d0LA>Y;T z+WXPf;K6Cx@`VB_upoPQo^0&$PDQh?Pt8^uz6k_X&}Sob7yW`z1B%_C3M!qvzCJKW z$%?){1C>q()1r%G$B6u~+qjXY`-wD2(CiGdx-PF%FbP$ie6GZas^Y%wVVJnE!Z#iZG<=CIVVCv;Uje4Ee~bczTVaVz)noA zN9>g4h>A#E1akKRl=(TsiW@}*Z3E_2a4TNJ0*?)7#sq^2AJp(GQ^Lw-I3z~GZHC3D zb4cyvXaY74501J+UaW4W%^jtZ1Raxgd3voS8Ay`YGR4({3%*a*KuG97HdPVFJLoB~ zs_cnuu$SeFj+XDkCzMyyg%~kbm9kt=mU7BUo z5IKf<{$^rc2R>5>W)9f#6^YA_^{VFr zL{`d~Rn>{o*?c24L_)M;~{E*p~xisf5OhAIRK(lQ|2Hp-#&_ z;YJV2J2-*!9#46m>ry#sqAVd^F_7P}Jz^*;S5-nyf}bcTSDmHpX}MzcaRV*M_=u~p zAuW$c$!k_|dpo|rXK=Eh(yh2>zEG)3`?Pe5-O+F$5I$%UHfd~h71KiC`(o7WcdWK@ zMF$7bcri=>4e;jJaF7O{O%zP;hO=;0>4f~JIU^P-Br)qy1T;6O(uz0mS#WM+t4I(l zk-=H=QxwLPA(0)X|5e&YCohhQ$?3`9w6#?n&LJgPJTcn5#M{u-6F!jngKO+?B`);h z{uB+gRB+vjMuKUiDBIdQ;}cMIBxVr6R93H;sY&r;u)-=lgQ}z*9!wpIcWj|)eNzRh z3QuQab(27pUuLNc=s-_Y>}n}W_A7|3?VN|7Vm8p5;<+S7)J^pDx}yMTxAVsZo;;e9 z=>bV6>KbTN34>!KMoE9h3Q^7x35|eh@x8kw3=YNStF@eX;2DN45hl?@hyqm@E6y}(4Ik{RVK7fUraV&D@*u-Ugl$v461LO0-fs`?$ltw!GEA(O@aFHLN;<|FZQLnBnVrJ8h{M2NK3IjLbm_48j|cM7v?H(+%HJ&t z13QuY)FA$MB%B^2{9TBcT{_rb>^aTL8((ImquWA})UgzT)iV2Ihg-6GSe%*^uaS9J z_s0pywlX%m8~2AsYQFq;_6yr`lOo9Nd3g4vyOUT>T+W>U(EOTmgq-x@=w^ruX8m#H zQ4sx#-;Y(%=008y0)PJe6q+o_>eDvv=#Pg>t$=Zo2>LUL?cB>m$&*wyn}{uskR(dF z>0cR>@~{+FnZj`!APJg!^!?6z0Ue86$R=PlKYume-=vi0;qW)i_}%S1y1F6A9kD+L zHA7M#lX5y9rA*+K*(aq;%aUD5>_a-lp?@u3WPlULf*jSJsJ%?T03jxM2FT<)U9w9`h3kFDGuf__9ph5rz z9fP`@3UfQ5Mglri{zjq3CBy{)`bCk&JzmjmV@r0zGdBF!`$vy&c`^AN!b{qJ1HG0& z8Pq3^^7hVYl(U2*s`;GjCJr0Zcr6aA7dkDf>24ws)ObA>4`H!WA<9q~qL$1o4qHQQ z5sR*?F-u6(Szjoi`Rs`u3(M8Uuld{_304?VLt%dl0;$-ugoZ031t|2b!SjxN&0-4+ zHX1H7s36vid&Q&Yqf8}6l`*-7BOodCg|y>eG)sCA|3FA3_%;!T-tFlgDhd45ZTJyS zizEnD?A~`MeFUn1rzZiwM;|WIqedF2#ST@7ahOM86r>aXgjBf4zJKWt;Dx=tLp>9R z_3MNKsY9sKz=1nDB!pFn{>0$8h40_&3;lx< z`I>?d6+f>bkfmKSS6evq0Tg~9cLjkQ`EZm$X3u0q2Z-*V^}H38Vq*mVrV^dVw=lq@ zj17Fb-MsALQAKkv3Ml!KnvH;F&gl-8CG700KL_D?10&?@t1`?e(w+Dj=%IgV3d-Hc zm%IpYM*BxU7vmO>+_69m@eI3sORHvVMsas{hv4om!3pl} zZovb=-64ab5g=ptV^*Y{qIxwLg#lKJ?)BS8}v(;dS=5GNW=f^xCh$P=CpCYE<-u`Fq^J zyrCMV{u$3Cl-8^WzNb4`Ybn?Lao`1kQ2@>?)+cGl6{74>;<0py?uxIL)cO+=fIRE(1-?x=sGuC<3)~=o_5CaIg+T!@1SZ7USlaz<~134*tQ42;=IoTcS zP5EGFb`=Ql<9XofRb?oTel>JJu4|&M3`w)QD>#H^>K81X^d{@sBsx2$-BA)hH%ieR zS}K87z%9aPZmiWJ0JerLf+z{E1M=mmN*S@L3eyw z)8E&wnt6xjQHZgWJli>sULgYol|qU=j_#p}FW4ty6E2rTR+~FBm(D|Wl1K&z!ZW3q z@-1K)EP+da#pb--2h0W)ECiqf+BWo|R>hnG>S<8fQ_8=#M5rYb-1jJk>s=^@y-qxz zru0v0?=sdL-RG-m8ad{L`Wo{jOiT_i@}}wwW%PH^Lva`^_i9isk{PJ1IH@sdvCTrBK6P6W0{;PxYGW}@s2X|fSYtF1%KX?c20VhV3%mI`aQ z0FneU4bjtY*evt0$#H@%m91rhy2(>%7GB}1-zZ0ah9>J%dC2hVOVftWCVE0?5Dv_) zIwD^Se7*pU9|;xo%&=wBE_-DEMlDleIKP6tZw|_=rqyTNvQ@H|BpMKFXlHzmaBIAO z2J2xWIknkna$5g0p+iY~hF6_DWyao`?V& z(cN!jN;E}D`$Yn@Zs~rhHy?1=UuLDoh>gd-r26n+2QK|bg{eqv0Q=cXuFq@WlTzyw zr}?7$&A{mdDCHn+Ggact^GzEr)!lr(_zw1to3DlWmT_M{_2lsS0UI5!Z4?qsm?u^OY#u&TX6htP6-*c zrlp1^4ftB#`86a6VHb=~RPiiG!L;Idvc^_}L@Yr_bRzIKec5y8l(Rf%ioIP>LY`KU zQA|k0$xCi8YG-32gv@DB{|N>;c@h)4+j?~6XbE~v$ho`Pmq8COu){<&bd9m1>5xMa zLrLZC5j9aFd>~uR*Wk@)15p7no+_2gc1g*R)9n@HSgn6k!Vp!K~-5Kf)!2<1C{S> zgO~r`p}PPi3ub)P*+${ZP1MOd$TvseMZixA@X9xMlrFtQ`O|y`A@^9I0_B#V)WK9s zqtT``d|O8|Nc+=*`t}(Q^Q9&4J3zi<=FJoA=7>mp|!V)BX+QPeX&| z;>1~CAuM3bU$#}{K(VDC-rP_vIi30e?XU*qe^E`L{}Z4K+R*zeH25nKh^6&xcN=^U zvLL_Fb2EW07ENSacXO{b>;wMCUdmD&YvG_-2C|~og^RP%#*1i(uv!y1Kb86J zkEw4Q2B%53vWp?Q5b$o;ksebT)UBf$^iUv1%odkVOj8=4TSu45UJy{p7#pw9jx@M6 z`c~oGLTwE^0k*~yS*_v)_W}m>lOW%(ns5cEN_|4g;#-o|!%^tE?kF$@CvsZW!yv}U zhAg+xuyTF_ldqK#VQacxx1y4o*)zw{mQ$cBQTib6M~$K~eL-|}^Z6qLN*77>-8(UL z^NRdi=zKQa4Nn!um0Y6PE7tMLcL>Ata z{`tSR^#|mi)*V*;DQF;t>1IamdMMct(dQ68Ti9gt*C3)& z*t9Fr@en5KuDW?yAE~#;=dQ_WIdEcmw}=y$Q1Qao=lISHldhAzu%8DOrKs-*e?M#p zRc$pG^x72)WaXxJV%)}nxqcra;-m!R`c3P%Q)sf|0Yw(<1>u5)qqNjajG5;0QQ;?L zA!(7n5>hymy8yN`QN|pUwq$fk8=B!(pg~0KCfeWYNStK5{UNW@T+#-sHzkI8#tZ*C ztAK`MGvraMg#7B{sPz*Y-U0!b1TjG%&`Mk;dR79@FINk7<0o=-Q9ZS9moL zi?g{e?a-yhCsTf$kC=v*kbj|z+oghtx>rqDCj5;oIDjbBVyeYvCEkr_I9GCbWS9iD zhbA{kw07MZzvOD9mY9D-b3)6f@yfj>7+XgGIRvg8HsKn~u6U{_Z~>7Uwr28d@4cxN zc^z^WsgQxO&PmHCqLE<_@c{C zZ4uwI=3&#_lreF2@x8S`_A4~1o#x&p&I){B@Pm0g(&*+~j@`%6EKcrd%1zBkZddDa? zGEOcFb^ASJ(qm$k!Vb9M7Ef_0CbCo(c-uq@DW%|lI?d>~_BW2Rga~1DO6Fbj8_Cti zKm63m|I7{ZDY`ss>ZxoJHX#Q9PwVPBUy__>obc25K;F4BajBlrCS(sFt+socu6G6$ z{c3{BmuixvZPL#lTi50+we)wAEEJI95Z|Hw7JB^~4kZgA`FAcP-|1nWVYmT=sNL5AjVg{T7eiw1^TdW?8m(u$&sw0?cUo)WkSMY3hPbO&;QP`p-k#-T4;yw*gt$LjDY&OX;k%i&9{B9#jsOqsyo04Knh4*I$(dH6f!)c=3?(28;TP5NcVR5Avq-ib zC!;kyuw*UH(7;d@4jaZ^<&!Yjb8!H%`FoOXQmep^lUEson;DH!1=u%aczM5OL+JfP zVj+KO6OXSA4vRjD3x_PM=$6yOZUFbZZ-?8F>&xDI6~@WP-RP&R5WDf&%;*>bG^i+- zKg#}%N^iG@5T<$e0hyzw(k&f8(VWwA(*xZ6HMtvoD@^Mv(E&yEc4l;J_91!wzc3aW zMdjm{cwUVN$=~@lASX2gYuSgAIy)c>2KeZcYbaP%_otOHgNT!%CrQ99dg^Wq7?W${ zmU_JkA=f#1uAju=)vySmYhD-7k)Zf#5wkSXYL$EAqH3!n<~897PqI*M%Mgl}dM;YN zbc-ej*KRH!t7uv#!c1z4y#^sGP~Xb`un8^5gxRAJJXS!KKcG(PMdG`_D1*|RGioK@ zJdxA6D1S;0RV_rbFu^Qiwn0=KefvikN5zz>dVtv=Wt0=6fk1i8vW#|mtfuKW0y9~v z1pG!kIW)AqwSZ|>ys;uCG14(j!uJMWR|mTr0v>f#oB$g+VW~(FnVi_b z+NnWN9cwe7rx>$&>a$YrAFyTS_?NCWCe)2gj*)BOB=0>Qx<2! zD44^TEUAnms0TjUTdQp_Bd((^sdLIR`2>OH?-Fx)rqGlJ)7I@FWlsuVPpEolnd8gK zU)c8l*w$`e1GC+qwZ_>Td`=vxM`(AKeC|O00gciZO(uTFQ=q65VEIrFLB!UnF269? z3{`ikN`x(wPoRG5{hwI?NH(F@)gY6{EB*44xiAfr;dO5h1N!V(@P_(76c=m`G58^^ z1Wx@kMMx5)BArD^)m5Y-e(iPAXNFa)fA4X}u{fQNJSn|j)dhJnX#VpizrO!PhVqWo z7Y{B1x5>$Ac~pp7s?}=gM?ggCa6`a1e*wa${;G?&wHkMC&^H44NTJK0XSa@ZK$eu& zi@zEu*%`f$I*VB7fAj7no5i5hoS*SSr*Ieby+Szt=h~>6 zOu{I&IFa=L={w%3&NZLsL=j1v!J-z4F5h*Co<{D5r;#w6=cRL$B#|OZDs-#dfQNJF zX?$b+i}7zh*LliUXL*=O-$GaxK4MNQtTiYr)Mi)j<>E8F18D-)FYiEd7HP8G*4D8I zXVq8yOFU+U^tQs>7VYH!Z7EwN088n(>C_J0gd6QYelop1;b`~!3`TMB*`-yOMSnRO zD+h5kCb^(Tl}Y!%hEntRL&KcXUBkX%h3)$JvP)Xt(Xh%NtVB1-blDk)n-;4B(G2oRI>Qq?P*k1Az3hFlvv<=n?SSJ%}=RiDkwwQjwdz$VxH=2A-g`7Aq&@p;{* zBD~eY#$=0iuW+@`Puktn-hUq$4SmweleaTsnWpFWG$K#Hlyl$^K1$y}8#@#V)JHVH z@j}F1O|1k_Zo-Wjyl%PsFz4?*EVL6}nUNA;cT^2?O5P3UlgKVlOzZ1pDe0;OpBTcMt?S%}B+cd56 z*F1%nFp{sCYnazPMnRRd=;y^%e+qU?neKTSHGGHHgUSB(A-BN4Rc)>;kU^A^gaEsi z2m(AD7o`i&Fje6XMyZfZl6c9c&+R+ z(jW42dS)9TN(Yg`!X4P{mY0I%cOUe`jtH2iX#Tsp%raHuO{Md{(=dmR9>0jey>8efKSMPbz`q5IqfLv>FCu1(im7Iyr6VZx}dk+EO#m z6^&aKE#0rTC+ksd0BH{qgy;`!lW|rQJeYoY3B3m`T5mj7!+0@Z&%MyRMUG)5l%eZ zoz73EGYHjHdsDoz*h8=LDJwd>Py4Gxd_k^K^X#}%}B(6^$p4Z*03+3ESku!Sv2Bul$${09T3q$$MYoZ83%vC>wzt%=C? zjoGduQ}GQUM+slcx}^B!$MDB6x(N;@utMH3Ecrd^ZY--*(~^F;lx;>e#_vJkY8e($ zzrG0>N7X6Rs5io!>_QjvPP*Zyv1;_GjDNn3%WZo#Ov9TM>xj$M7>HMou?fOfrhnpu zeh<2l^8zb~%?xcXrn5HR9Y_!D;Wl*nI7Ep?sv#EC{(x38E$Pc(q6MX*;S?}h%6+d+ ziujsA7Li;~*X}G+Ehol1N67iDcWd|TabV<$#A=;sH;{j$#pbK-)NCf|dZO8Q`=`Z( zYt*JHGV{_PTzGQIyE+6arTc<;ss!Pos6z82N)Nl^tE!4-E}LM>vejcr6BO}CcazB$ zQhDa9DA}%9kB?dE>la)y>>4#qL!F-lY^aF>`{9^C6fkDa^@So2&-boL$cFbD&bXsF zN(oL}J=(fwwv?RRLM>}ikj=mH`R<=Bb{-TkzqN{v7efaM^(#EXx`>yPddLyHseKHR zs@ZN#ZBV(cqqe+4-2c_}HQwXT^1P>=?N`gb@)?n{ zJ#6T{0PiYHM{pfeh64k0>y~}lE>_<%&P3yUwkhvw?{edl8j_VB@2aMM)RsM>m0pVE z{JskB>O#$HQUdMRIS&;aR+09U7&?_v`f#0u%9XJmjPwp+4(l3P60s|5% zCHI6{>0NO(fqtENNBcsdURx0*Eh+V5^E-4pwcZVK3k20db$uBMi>PmEG0Ai?sj9DZ zQlnS}3MFq?l>aXJM z{-~-sxL=CBAnxJdL!kMXs2OPH3lmy{Lv@4GRRkMSu7&)WbBW9S?2zj79!A>3^FgK9|Pmz0oGQ^_W;D< zVlsBsGVq%4xE2*}Qd4XPQigtsuy>-X-B!X3eON`kV-oo>nkuQRptHbYPi8~)EQku~ z=9SrxR_nnW)ANQ+l+C3!XFZj{m)~MmWo!~8X(@jNrWrzkY)MQqjO~+3^*oGPhIf<& z5#Pg1ES;jz0DBgdK58#kQI;vb7EYzQX_T5$jk#QKrXi_&=8m_|_36e%w{|hqs^)dK zOH&%s{|rbPrfMAqrMnE~f}TK{uAH|U-8nhD1OeoUR1bkm%WYa4!4_~@iX{N57=QFy zHIJJd?k2zT(eebk=k@s?FQ{^BfUG zv^Ms!q;1TT#g0o-QNN=nr^}x8{gmc6MlvqR)hdEpw)c#A*=_ibdH-N?hc5p|g^#ob>%PSLg~oqqq39)> zVf7Epl9sPq@?JOGokpDR?X=aHALr47T0-y7&ou(~WpqmWG@lP6CcZM@w4K+$csf4| zYxb&AL*K}pQU!oXdSb{f*H(LCZfZQzs@ltN~uA~yXwP}A9uct(qdd1ZI-T}M()SZG*>|B*C&E4c&~xuA}xK7 zlOCjG6x0+sA{jYGf_R$IzK;46NN|=caWZTeJl)QCb%33$jpuk|%Z}0pUgc>8YV@#I7d>o8RNCJpN2_&)^*^APn;@OMF5rellh`I<3TAR(P zfWw*0=JE!bpXFHgPkn7!jFgvltt72x`&vj6M@ujI#riY~llH>`me-A?e!K5U_q@En zU022P_2e&|d85-m=)>O;y6^HfeIcQcJ-nBWi2X|V{_r07x%gdH74=@{qBPoKcY`(B zMq$c?$?{~XFs@RfyqYN*ROz2EHetfKNRtmyNi-!l{AVU%9VmSwYG8RO3C|a|w zgHzW-q|=MUnFYc?d();BMt;FRt!~L(iNy1J={Q^hv)u-f_b$^VcO#WNTZq;itoG0E zn4jHSwB)XKo|jUW)%8ezwp}KU3BY2x*>N57ily-Ab+W$4HeYWI&mAzo-ZjixbG0JZ z`k4Ocxb4Dy+_k z<~4r9!$t`qEgujoU?w+W)JQG2{2dk@{*2;{qN2r9ze;!>Y-#M_UzcyeKM3>MnqWsUumH7NzCGuGoIfB zH`JmXmX{kM`x>!c9HRdfaPqp76NGxER3GTCxE@EDj5vc0KHk?{vbM&&Nj1MrkWeCe zieySvL_0$l#?{JrDX#M|jCR3qQcDSOk#ACJQyei(X@(0V(xD43_ zbPBZ#2N?=^XR*fSyauqW(o9ncs(ek(?G!%8WjS=N_!hY83*84fc6}&as5>%bE&k~f zSo)B-HH}o5SvFP{gh!yQ+%r#EKJksLfn4+$nE)UB%F?9gH<{c+*Ah1FRRR4}!p{#B zl5NFK)TilWZO6z{YsuL;hqzQ~8gNGD#QZYRX+ctQx@%vDYjiPLFrmrSu-kX{`AB85 z&SlGF$$aCmKe5kznB2Bk_$GFv4$bIu+FqZe*~=y!lY9xv;qa3~bOB!j?P$Gdy$|y_ zhV=~+ErlP{gr13uU_if7g|dNf(q-GCLi;EeWR5B}_ZFCeb`qXh8}W{%a_>{t&*Pcv z+gU})R)yHP@UeHhJzC7P7elLk(zS|YL!p=?YuAzChGXf^`rS>9;znghkBgXIi+ADO z{OpivhJg=7X}JvDFHQ$KBeh)a{A0LZ`a*yQK&LbYatx+x01x1bqa1Jy)?Vm=W|lUf zd2r;+nNlzzT8EE2G}CsFvN6<_HI^3BCKo4aKK{?uZv%9F#Q#}50jEG?)s^rM(V2_U zr9-|Oe{+4h?=~krdrZ7mB<@34F0ul>UpQWk{L{%jNz1OK4 zo)_yniuT#F?e23haxhTT;FY1I)uCR~uzIu(!4CubZo2*77vBTQDNn&olEv^)uTQ%} zAxQ$IH_^SIK&M1M!BG!gUN~-|;})+V32=7rlo*^?E?#E=B8uX7%eh^%uTM?f$q>oC zDjyt+gM!t?ifA;*mcf5}jDr83qi`!m$7oPoS4%2JuVs7Bl^PbNhvE|7737T~->`~M zq5L?JUx&Bt8-@pJ6pZ~7@dxc{>nvy$0|f!XF8&SEIa%g$3|{7^+< z%lP4}TPo7;tlMi-@`l!D17Gy(Ndl>e8q_W)+pr_RKm;TyU# zJnCGqZE8q)K8y8qS9+Hlx95`X5r4wXHHuTro3>iNT&o>8q-k!k@VDkHvdop$L6A4k ztUi1PsfZgc>bOVo`gOU8{PUu@ORFf76&1UVdFx`VFwxJ;2uJI2ma?otXQ>ks#}#ABRS(AkiU6I zKq{>NiohL!%tmO~@#a}ACdQ4`pe)?^o`Qi|fn@WWz30GbcS|G=-4i!F54z{UPmWc1 z#Q{fZg@?bUNKr;aLET;1ptVjKqZq|E?`cSG*}NWF>p6^8Riquu;OxFNs4Q$6e?Ror z&gC~{+pMrR;d18g8e|{{5Q*!u69!~q#o`!Y&Akq^UyldTa7nh=pN*S|L&%v0`z^S) zo%1my^t~eFEj>rq>+(+UPC9Vu{Cgn%^RP_IEStIhD8O`xvP>b~Ky-*!g-tX3=>hk) z5v?-2E)Kwj6@-W{b=Cl&u7dr>dm)2BLfk4{5}}8tY!*Fl8qcH&Y0#)`vBxxmx7tMA z-N7M!w@*tDZW)WtE#Pall;ch}>Q>;TY3sBOZlvk|vV-=T`$_fKL%#mHOr+hu%23-^ z{O7_i>#l8&v#3V>*@YvW55LPb98j9HNS*#*O<%AWCFIk@uR58srIvm@n`n6|FJ${G zLNY@TUmIyA{-OT{QK4T@=5e%XyzBMipl|sky`nLqYisgwskLe81LKER%oBs-m#4Sa zdnX_Rr^|imW|6(q|9R5mKD(tcjwlUgl)^w~j@S(r(%ejxd05i^ZO-D{ul27^dxW=` zR1EpxH9xjO8$f~#9t*`;I@lF6&}5!4+W_kF4;I~X@nmW< zIfHa!@==6{T8Z&X+#!P{w<|uNmc|CAzc7g!kif9opKr#GNUVF>N)?2PdHFFqgo$vP z@7ZfiB&~**$=C+R2T}VMZQ0$7X;q`!be&e!`|B4X5^4fGG9lY&pFOrssv45M|ZT3t~U zhbZON(7a#_x-J2ua3xK21+4ksC5SEScfmBsez4|qQ9z6z7IGMOeM$mqocUUcS&`m? zQM#G;Pik%=vR1uG7|f76d^2GTFyg-|lYDr`-whT()fS1^Qz);&Z{BFV1E))qMhJd= zXSvzPSlyzDd%kF13|U*-=xl}Iso#c)nFDoBjM?~UZ8Ok2(SH#Y^+&&6MUACKHj*;z zC#&v_RZ(AllnO}TqnCZI?PFQ6C82chf}#)pLD=+8QOAnN`!$iS#Fq(92|L;hjC_oz z?-Rx3LjLy)Uy|wv&}aSTbdE(VX$L-Eq#lLp0eg-PCr%iy#)}kuC#20*GoH&nqGk46 zfBiM=zf1knytPbz+Q7W;7#hcHV2&zP(!|)7IKSC6m%(b=PY0Xv$k{qlOM15ZW8%tb zQQjhHmqJ?zt*~U1;=YMArV`y!+{@U(@^2iAd5^HmI*Z!uvkRf~)Y2+VO#W*^Y8;;h z)$7d>WJmn!)6r~^faluLy-#pYPPUBQO;A}i{>TpQQL-F+0M!@6CI4}if`Dc{-VBq9 z&B&PFseH958$K(uOwD~ELFTyG#WAS<_Vp%7WD9ohdEL=Jh~<6fpJ*$*Sw_G1O2*4h zhs0!w)0rXfN?+{w^Koi7Z{T7yNB)eC{To)#Ath@4jd;94j zx8ZLDCuD*V2OsHLXkTFKpHY=LA)ekq6z-(+>akYjqZMmx0)uGMn%z6JBZP1sg+%jj zC41UHwY{ae$8qNBk#hOobpt=%%2Sx@lLcfchR*y-a=%BPxf~K)(mQu%Cr7WW@%qV; zTi-dNJF5k&G5l56!8Ba`R$`i8orLc#liKF&DkRf;pBmgZpM+JoF@HX7F=uL3$W&n$LGk?C-wT0X1Y8Vg8=cU!c(O87;O-IKTJVVckgq`}5D&3gIC) zoh}Z7!URzP$kD7LQuh>>iW-*lBT8BY=Cu}V}jpEqhtCUn;Qq{FqMpFY0GQdF&dlQP& zT~w{m`9n?#bQ(Lf2sp5zDVYw7A8lV8h7(&tt+u<^nrj2j{!Yov4Qdn0*nqJ#F7+P9 zS0ys_Eag$TDy5~ooxvNWI%h397+#VBLlRrw@S(O=D(R%`gp!W!;-T1wB~GYmU}N9S zMbzf_QzHQ~U5(?D13s2etu1n$qpGx*3sRc0oXbKLJjV|cx->NRv)jEtcFUUV*o56G z=7NlD2`pqCMw69>-({_WYiHAxPFZ5_E)+y#FpwF?hoin23=TmW1~1lLw`Sj#{1KscQsjfs)H*x5Nrj7k~aNZZ8pTUOI^sZ8TR$KvK|1<2YZ_@CH2DMItc-m@?a2p2>~?nqMZ^P2gHjJNhOpL z&qE^x-*cbLtntS}5&NgoXyhVtzo)rWIvdLK#r1{i2F$~G1xyVnF8#tQ zbJwoUVqS6&b=5U)XN(bv9hA;Nd~srbN8g8dPapU1FHS}W>o4v>fZm<)1mU1Id54!MyTuYs(V}F;mKFD)a?YIj<}-I0dW34sJb$^I5?(}aDg&z_ z&S19G4ka4&8&B#x+{eIo{!5YUOE@7qi7z2pa*2WnLbvGNL5zEcYn159gT~0t(3RcT z%@A6f2>O91V$E6IT9D&`El3kBQYOraZ()dX=(uxA>Ej>On9~owdQ^16v%LBc6{A}OfSgKCb1O%;7ch`&mReNR32^f5Iwi!TBI8`gfzgy=su2MdahN$KLr8?#7)H|!6M|0sNN-vN0 z``+N030A_tcK7ew%8+i`x8&eNlHbq%{<$(rX=-`q`+}oY<&!1QHAaq^#d^Yp8c(%cd#FG8}X!OH|h}+&Rnrpt)zXH(2b0$QN57S(IRuV^SD{*}yQdMWh^)DI4Rd%>I<% zc-(1lR%wd;3{C7yB=uZ=cGY}X$d9O4#+Z4qx;ymiFF^yAJAs3yb@-xYHFVE!@mvfj zDi8xQL9~Gj&87MKCe2*X)_9J;!3e_A#lr~mz@N~h`LV(GX?uxe^T5yMtVKzu!JwBy ztOFLB<#@V`RhGSSYKrY)rnJ>($g}FgPRt{i`fU%A(b905miHn6LKpe6Jiw(`knGQh71208~ zn+B`+tYL)^pt6XSV=~7DX^rQehUXpu)H!>O0g*Q=)@qwK=-@3BH|>01RDVfRsa$V5+oS- z|F>ZL$VmJjQEteS-AW0nSG7=R9KxjBPTp6@RofMBXD+mLFfdi)%#R~zeAJk~2gOVQ{ zgp8#&;|Li1rm}_Bofa6*8esY&h9_#LKc5P2JPUwz$qfK2cP0rpaWB-9vmE~!2&@@T zy-;U!tYV}l5YTYJtN^y{ z_*WP*KO7;gC{+kDNVF2@v2j2&3y^5+YQ8%tCXfTo!PWn?`_*I;G-0m5gx%>w-|1(f z@P)u6AH=w=fP*krWF&MqO9AQd5e91$odObMF2;ktn**ZB)dHeXm$W;C4+q$;iJ60@ zfBLQZAPs`^w8at(*+&A(ot4&(1&ViD%Z_b0RV>>XZ=r3(;??$vFar=vS2a zdaFV!Vub%0U;am@@h?NyRF*1EXXaA`2Z z{()nH6W{F1rZ<% zGGQ}-2}^OSb-G`2A0wB_5p*a}Ljyg@l22RpYCB-Q{oq)eh}&Qw0g-|vL9oaJ!D6~t zj3_6TH^BBrjOZWs!Hj2sN0|b`K20VL4Y4WIld>HD-aqkHOrbL8@WeWF#;bFZ{ly~j zz{iysX$es|agu@C5#^9^l8O7_)bmkIp>%gjC!oNRD(OV~3hZE}SdZ#ikI*Qm!c}MJ zP(gUj(8Onx1dJ=O8@hmUfOG^gXqX)T$1txNiML^*RA4{()86e|&0HA-o1!25} zVEuChBCQhsQSv|IYOBKCq5j7ow$mTF8RAbDNG*MgYnA}D)CQ>~BmMdF-=6y_0{6}5 zML;i;MaEkIy>zVvo>7L{MuvpGC@H^e5idwBU0o#Slw$Gg(K$eZ;r~~#RFH8U2j*Y0 z5W+|JDFU%r3bh{^Pz+*d)T9bvnC75iE+?}t1OFkMeTEM9-!RwiMPzPY2`^q5x+x#t z8UQ^?g+?3!^eEIE&?9lxFRLh@!3T+9xuFd7Aovu^|VU z`~y=NM&_b^hU?8+rn@M4?ZwZtA@_3#DIy`h?}ztUAhvM*C*?ZsK(;&2$gTjQJWLqM zmCAIY=9avr)vqDG_Gvro^*Q`>Nhfk4u}Vz<{~%S`_gH9#)bL!&=~?CGZW9I-b#c;} zca%jUg47O#J9;9}+KB?Joyg&orzs%OH2 z&Bxx^cs%qJN_1D-)pknNcqt#RLG^+}f^vK^^*pfeX!O$rT1Pav<<0w@CfZT7RGpFR z&lgDs7Nf-Y0qE>U5^(#NEb+Ji6daZrDg+3Dac|+0Al;Y-bVJ+C77A_!4$Zos;OOQb zWX!e2JX9f}gn;{VFhKXyukQx!fvl1X$SU!b1b+z!3p70y3;1W1-m4D*)n#l2rXpGq zHX5Y|(ie|9^ZcJxl66O)l~|wa7Q+pMgtiXp{ex6Eaf^;nK=KT;VH)u z!y$o8(-Sd{9$v5KLpwe&B-GpxS?Sw2S~vofDnj@_#*{) z67nDfQWqW<5<|d5vB84>Q;qw+G|!b(&en&YdQ$z?FVN#jh!tDs*B4rOGHEGqtB2e6|-z_UbY3Q0s(sh!=%f0O> z`dLQE#r^K`ypMt1gE&0y3oDtk?BB&j9+stG?s(V-1)D@x(aj{1_p)h7! zRJ3>U_U{-cbvxc}S3%nMCS!uflS}dy(gYm=+QMzzg{KgNJPU;v%ws0V>1ly`{2?oD za+#a@IneR^0Vlz@Xz9_opNYLMXro|0=k$}2_+Wbz-=5F6@yI&8Bs4j?`P!9dtpi$j z`>OYskMIW>34@67PQ71U3peXm873?H$q!phYPDWDD3HHXontWPFp-A#$BA^f-!)hh z+L5O*uTV-(bw!-5_8RU?)CPxPx{*Y{kSBVeHZ_Y#sddq;??^xwt*u4eAz zE~b}#T^r>}Os5SzFsWClp=uwunoh@+cu4QG4CFRfD{=ogvVDafYk%GPxqngCB**bla`F}>i z-t`2eOm74F-Uk=4{hxad2_zK3xJj~?+jbCj&PZF%f0i8iwje9SS0RK8t?vvQzeA2w3`;B##F`bR>zTXnBS?~7& z1sSLE-eT`U#wYVA3BIF=Xms(t;QHkG{!iEXI=e)T&xQ^DpRU)U>1QC1SI>u9ZBBS3 z;cOa+sfqrqBhdKh-eoRyw+t2&T2b!%7!o~!2 zF{!TS8NMxg9oZXa=Nq2V5-cy~Qt0;! z$DAqe4I5q?5gkwPO_93RtdrbTEzULmNu5Ru@vBUZ>-Q^nP7mFj9LxG8n8lm7lpVWp zj>yct>QV!bgerY$)KYieU^j%);bFJetJh{L^mY>SuqR$3OHz?*AR}%Dx}|85y?!Ndoy8AHj4=4`Cyoxdxz>G zZv~dw1_wK(3l?jC`5TO%QzWo{t#K{iE|zYKL3xs(&p0WYsFoBhxMu57a&gkmS_h0h7Dd|~#!yoAS!6x+?n7OJRKBJ3WSY_~)VR8#?dF$IzSwS(igZ{{MHN5DyIbc6D93;noxxj0*3Fod<`pCQfQo z62E}CMw13l=b&MRq`E@!%R!A32V*L5z?e-N2`BjfbE@eq!RXPG_0o&=V|c-F2EK-B z;{F}j24dsu@O!IA@-@&Srs@4ZR)d!yU*dT)5h9&&2wme;+MkEMz5k4S@ZSYp#R+Xbi6LGl{;%i zIQrL%TQikgM8tt$rSs5>qSj>2_75d;g?;m=S;PTkY`Nucu-4$0q*wqH0RSl4@Rn6q zuOfF~1o7cG1SWwGjo!XKp0``aKc^1IFHZU*l0sQ)N%w=$7ty|>Qi9g~2oO-Vli9YZ zST|9e<$^yRQGHW1_!pz``bc5>wzGUTkNSvEbZ_?wJgS~aBHYtNKz~}QSsYxKQa=~u zTexW-0lr1K8{k`LwvLv&?Knd>iKAC3C$L3mfjlUFQcckND>mr;b%4%nV8pnm=PV{b zGHJpnr#b6s<@%!6CvQeOJ*d||=fY5KtHb$sf|}P~_Qa<3UZ2lxoG$7)NG+md@3f3zQat2QQ5zQQoET$a~D@4op`M%p?oj}sy7 z?|YP&C4cL99(H@a7MOS5rQ*9kY-T5=4N}l6X*Fj*V&B7TNBIP|GMrLgK3$^K9Y!wc3Dehq;ta&AvAj64f|R5^}9p8$F1s2nL`g( z-(kJhdes|iRrQTIWt4%8(LfdTC>*M_dGR)^^>ILSU&RvPMl5{Mzr6*bf1{YRx?+BZ z)-6T|WT|oc-sO?y_%oS-{)BeD?1fm24LcVRYqkV?wsiE*S1n0m&2v=mQh0CMcNhPm zSOig0x{COXKT+irUsmqz6F$@5B|!6ety*tr_Wl-bhIgbdR`UVOVi}oJ+kZ|1|2fsM zV+1yBR+P8@rhft72x_XmYSaj8f<1K>6%`E*5cLxhfr84RvQzsuuK-XB1!mAsY{KZP zlU07}4~<9Y*Z9`#tQy!XhkBcd9t7h>QMBNUol z@!g1wF$cQDoJG>@v;_0NA#H~L72iG?#ID3iU7E>&ARDHbRsY#AIcAqUt3He|3-#CO zZ`E%3?5kZRYRda?S*^>xWyPb;Cw-^E^mPJE5uEaiYA4oxhsgc)v*cFZV)vu}hp)GQ z3!`WL2eIN-+_kv7yOmGy8#rUQfH?xa> z9^c7LoJ;(?(N5nN0x8P>7@^u*di#3&xG=ZpZ(wj&X4MS$*6&3Txwvceppg(^deqpG z+n0XBGQ|NomXLy$RQ;^rw6nb*>q+;;RgahA?M3&E0>E2Lgl<>VggM>Udtt_XKmiqLJcZb zx3RUUwe|JoyVhEZyO+yLbjhy*THvFfS&=+lgT@ZGk=59^RA1)rmK!-tGTE)7)8Z+F zy>xO%E(!NP)!v8&tLw_&F+Ywj#a{co;twSnPDw5#VOBm(;twn|0*_x*%LamGe~gCJH*^i0u>1U8yVdl998=qbanRI> zZ^UTwqE&kgb?yJmXQYx2)%jD{zYJx8H_tWI`I_1FV{BA6ayWPm@(p{+&|4RND;ib3 z25ld^$_h!nTyG;tGQ75Jr>9%Nehp~0Z7A9FW(ip%%)*V`vLJOIWf)r4%+~Mej?PQR z9a|fN!g{ojF<_A5?)4@WxXJwBUR7^u?e!$0kK1k=&z>IJHulqpiWf|+mmdno`2#+| zF($;(9qcXc?=Lwo0nWUXnyLseWzG<)2)R?bPPLaSFrJ(c*A`#V=Ubg+5I!^=7{s>j z#NI@ zCFmUNF5b#bx1Vp3DCy_VpS0KHGBC!(&f;%%j>3ieaq!tSH;Zfb!qM6kKSq;CaTg^F zND}AxvB_P-Zef6d-^+6R1T4?%xxRIERC=e4XRg(B)*{->7SExVPE>IJow5h$FV$Sc zl2yI3p;7-N#US&Y+Kho@#glr+$!yQp`V6iQC5b9O#tjrUwROU|8tZW0W zJBbYos5{;rgno)Vl$946%W3t`>%NQQ#wH^uz5~VBKwK|}evSBD6q-)=+#4|lS-3oO zw=?>VG|4gS$<$qIe|tSSy?v^8-fNjT^nAO`Uh!!Qxy@5>cornsS9RzjNJ(Q)Rm;Yf z%Ry*6CB6B~!F%xRA83u@&B^Bp1an)xd?vclzuh@hd0s{U5T-@j&2-K+e(Vp^$8_J#H; zSzy=tJihZ4^CiiLznN?BA6ejD#_e$}vsY-&jWc z?uzS5FUF5Wk3zAEH(nD(k7(%J`ZQU#JE#;&`t7HUyfld>B&qP>nav+rnYU){Ha={$FLe2BJnB-q8O@S^_=?oTZ*kr0MI9GP_uuEO z0ZIEh6Pl4aXO|7(ua?#4^ZbXc31UTCB;6S=)e1Ki(`E?y?rMh>J%V{2mqWy#XD*l} zuo_cN!GV*!btKQI#8ADou*Q75W~AZ(L>%H&QvH z26H-84nLDM%g>NIqO6n?=5-T%P=elm8T(8a_nl_?m-TrmOMmc)ikdM$7U|;8izAr7 z{hFXwnEA|ORnWuhhyAvJ)_b5u~OjYbzw2B`-MSn zDOU)FUPcZvhzfK)%|0;dEtwq_*z+Q&Z00t-0XeVxgbO1PZ^W*`*LanmmGC_{ABp`= zd5bWyn-rZqi3IGoz#q6k2h(Oa-wnj)h?nyCOoqHHRBJe7 ziOT|N5N6%XO}>sbRVHHKZn^yz70n^^T*xexplzW`6t%0v#2vU@$QAb1l$j)Yi!91B z-RGkp%S_<02hpXl#UYoApMaSHuKf_St2mRe|7({3L=!V_%;WbPWQjS+G!=ws zlw>+suJM|M)9ouJ|7QVG4t`_d{*6rt5H{j-1jSr_7wRa4qY$J5=5=t-!A)?*TyX*M z7M|SImQRd~c^HCNSXEmAF!1*vg!jy7jEwMhuCmCP0Wc&2;ClWbgwl4Ga&{dO)(?I# z3b`>*A~9Y{G4g2t9HZ5iy) zlTEBI+iY02?mHEVQuNKP%LGlI+=+@YOdqymZ<0)@B5X3;tkP2vCYaqDnJ^5_Os)8&QVj$Kd+Qi9LA=bqCaxT=w*?95KK^j38E(K?>DM{aaAnJdx z1ah*sD1ZSTe*HhZNMK@w%?l6rcc>8DrU0QuUJt;QeZ@w+AD|Pc5Hzn53^M{SLOHPi za*0vM7b$~iFoj4guD26HJ_wXi=(-z9F=P3@Lv$L6FolRMjY!P?zaEi?0FNMIaS2_8 zK5+mTI7ei$16*X;t%|J-IK9{?c_5r_XJ7t{q2yCm9!2Ic9C z)ItQCLL`zxgu?_p^uE^%1LyC6(m^Hzp*Hl_>VlXE`M+r*LI$Md-2bz+KNcO86|&Nu znLC&_OkM1BoKIH6-VDrTz0XgPR!N@V`0QT8^mIhaN4=Np_^Np22u0+VOko0D(R>ej!ylQ1x6y3JZxyz! z496}k&MW?E52 zzD1ev&sDVL>^uFW5%P$1>c1w|Rm7igC&O(rR=Q7Xq8e%BkCo&m>erHyzg&P}i&k|_#e7~w=a5Z9x+zlV``TpiE zWA&7YT}!03l-EL`(;O%S+L@gk9-q)3-wX9rJ+bK3*=wRn&)y%zK>bke>30i&mgEne zRfg(nOIAp=Pw-vKiJNAR>Qz?cn$%ag>(f!&xE9ljr9q5Rtl>7om}5VW>>24$g?5G zB&Ci0r8N$XUlTBANcNE?qFkw13$=ASwj3uH{-By^f!&x-ddU>mTy{$&!B#7( zV)WMC``6J2tk!#rHz*Zn`z2JJDlsq9s(lXORja4Yr`A4#4xFs{%h!LsJ-wJ9GWg>O zun{2dt|0UY(0AVtHQI;2ej@nanI3u=<9LWNMeBsR>}+W1UHW~7U=$!n2J&vM_T%le z$XR$KyhZ7<^Ulyo@D>>3C`5zu0ag9vUncbEYvKxwN)%~c>flK&j|wY~AgF|lDXFO3 z6x-tl)%^1)i#j}{=EfdwxqoiD-80rN_@;K+JU7b=MB$QxyeZ9UQb8H5wl}YGo2W?Z z*9LcqS}tAbV)9N#NHFNGtgNnPt*qkrk9@GFl!+?2b1|(q_T>8UeRmppOyF$wcI>av^glx|j`m{Ei~y2etfJ)%ReGe3Lc(BPmjv;i93tVU>7pt+c+QO>WP z_6vCtUtJ~SupbvA)NTh}3b=zF;`<-vU{_mB!@iB4DTS`x1Z(nVS5@HzHxKIerO!K# z2{Y2Q_OdmHc*ZO3aV)uas*)?l^ABY4jDK>{u&)XDlH7N3hiFY@g{byT8Kg)r2@{QJ zGz#y;HF6kXdZU{kaGV`jp&>}B&1|GtPonn5=kLGv?T3lFoIT_2G-t&U&m))h7Z1?d z38ULR+AE-M*C78+JsdNeI7L$Z-gkKTHK8m8(+y4QBqR>&PLt1YChyQeF2s$_O+Rbu zO6B2Xbcy;h7PEL^DNg|5N-zsGKKSg}4dX1$wXPyMgrVp*nk1OaUyfz{qs~09a^YerRw<5v|}Y?V!!AnwEg=dwpG01#>Y zS?odTKygz&bg3RuVY@iQ3~=_>Z)<$4XM+0)(SFYYF3O zJY#f|#iOg_X<>oAr5q(=Wj@B*cMqWX1h~TX0xo^LQ{{gKjO4RZMgwWz2H1XPKeh#E z$Yhb_*VlL1@gH0|I)g*(5TWfHINf!4hwmr!Tm(vtFF$eTLFy16sHgSzIKdM67LxMY z4t|bA@}yGO0>>Pv)FMKkmtY`$f+VI1Y6RWN`*YvH8H+=RMNzw{Lup z08_N~X7AQaNV5?9xkD)-e4a8Xw0xvnaw<aaPLIqshQamy5&n#awsC5ai}@X9fznmJV!?-T;e~V%Z7EPTCSH?!s9l>uq8#7F=I?sA@w$xw zmNuzlKW~Mf{`;|_o8@S zylog8@IGy#wyslKieKJ~6_edwUM@3^Ht(INu~Y)sgU`e*5#62+*|5_pJAy&8ZylPx6W^tX{ur}T>FP>ia@`>DmZB)ovXJ{`;I7&7ar>M0;90kQ z(#8AE4bvEpqpRiIwRW=m4BU;Dp7BbKvaC{4e%uwtWD|+`B3n%ro-}+f1I0aub0TXC z+PhpI%62e=ore#QZuQ1mYfj#(HtEDgJ@4p;ug+oT@SoiyPO&|SgD}m@D5$M&PS2vmeHnQ@=$n)+6) z9xXUD;&#pG7JkAD6f^Ng5#HpP1K+l|fYlnvSqY-BCB`*SEx#`wU!fgq#SCX{w{H{b z)RFJ`@!4~|N)4?LGw9KznN3?W+$|O_%j(R-{IJ~6lF20e0D)CgHaZZPAJ>T z&RWFf9q5glFJXZ^ z&h0yg@^4JaU6RJ0WUzR4M=^uvzCP~kLJ}}a{vv88gVF-tWNFK45Y{p7N5|l{4Qe@z z0?Ky=2mwH@&8;&*;gdFjnGG_6m>B|#)+YCZ2OMpt0)eWj@AlaDmyXxen2&7KJIn5sH}h@zF` z^bN&r=!*RSP(9L#{+<0lq`b4@ok>BYa9wmkq(|UDSO>2xuOnSYyzxJ9%r4K^_?mYZ zTB?&jqVgGSgN|Sux@xQufx_2e-DdDr2TI;6_s$P@qdD|ZVt;lL)49r-PP!X{-%Mnu zw9Cyq4WJi$)u~4x&I2Sxpda?2)&bg6?f`yxGrm_1;6usjzj;vel+Aa25WsrYqaH87 za6-0$&PCk}=QSYpIaVia=*ioFlm=OcjmK~3BAdkn2>)LkX#gCIihk^c^Eepe2g5hg zV^!H9JV+scNkQx)BZuMG&ZhPSDDHxY!Bo!CE1F&DA8e8e zR!eblXtmDZ8ae1ZPW3gDXz^lnJHdgz(c44EQ^r{HAK5!xhn2wiw-wQ&Xrb$`qe_u1 zmMTM%jq-y9q)@0!j~-|n^f`{Akank<&i(LdIQU}-0VmWm;Emdrka+je9&rrFoxH}N zj3T*m%YxdZ^>2;^SI=>f@!|u6ny%+f#VMFlrk`1R?!4Iw=YoG$(s?#Ve+6HCW4-{J zB0uk}De_kbfAD(-AsmQ)z8Cb~?gQMq@1->G5qTdr@?~ZC+FW3zv-1*ODuUyd`W>0s z_DTblsEB#5#9tA9mw@*!`OZB%UzjesJy7zWK1YlCgvP8MZ$lEBifem&Df2%#{m^+k zOUPh|i^p%zwb-zEhWnWHpy1TCkBM9k4WJq=aGYa!uqy&G7g&Ki=Z}KEa=SO`nCm0p zn*3|^J&!j*kb!LMKUP`ZxbS%6^caFKA)OBmf=+p&=BU+W(*&2D-5XTD3O8_}Ku+&SfJx);%Y?w!W~`*~1b@$X&GcqA!YPyY&z zdRum=l-Fhh=ucfb0pBqR6zxZo|VkH7RGZ!W0ObB)!ejFg-T1O#F$e^C@aM2$J#>TU!DElFqD5IAW z{FBYQzy&-&y^CHy)FpU1bdQ`%`G7<}Qp*EpiiacET1dpUpAE#lo^_BFtmiuJ1n$4( zZ`UCa3B(Y-oKqd+Qh^abd?B#uZxTE)qHBaD__a3Uie>t`PP^=_raW%1-h>F`8iv1w-q*1e z^f;1lC#T~!RDaSBeKx^<&suuzzq1~U0#wkyDv@Sc9YllPCFwq9Arcqahd;ehN08#6 ze>jYswyo7mrrZ7cjM53Uh!s()>rKznho8biV7T^FSfrnVUfLwfPSm zNuQ28Y7n%TtibzxtfE(pc54`kdDkvGtVQjSO22(|&Tx)fz z6?cM~te}90%DJdX7VfxRht#4vKa5uL{3)0$9AM*8z-+~&K>=No9`G-H|8y2x0#KmF zxAP$TX}9yGa0hgmX|j5eFgLt&Tm9|+P+wk8S5aKV`Qo2S*7M>ZJRTzH)&X0TlJLLu z)ZaP-dBRel`|=0HAO3+Ew$qE0!S$wo*yu;}d^z{i{-1i*`roxMz}-C%J?tHIUjEd` zsX*v=FX^g7E2+xDX3D}%ta@hiC&Vk!JwwIAbjrj6Fr0J5w0?P-qjdqGtsh>=|ULRW@hU{Ou#A$Z+Zi7 z=;v=Wns6SCX!_ruO>q8pzP*3VH$BiB{_4QLL;$&VwSL%8`NlA3F_)^gJY&4L{TTLj z%z@9f`V+DLvj#x}&{0dR{;}R_OaIZv|3_3(Th%2%@WHgo`-@?TWn{57ZGS4Tc02=Z zAONmF;^Q`>ez2>j^d!+`U>qRWN3oWN!*1Yi_#`h8LpKT2?446FMV1pnOl!9d~ zxcm-+5DE;QWA^{o#W&7zkQ#fz!2r)e+s1nb?2FXdn4^C4+oV z(`rF`!MRU$6xA*O>hR;O9~T(`zT#1=?7%+N^5{LVB^Rl{D*hvxpTvmo%b#n>662b# zw-zFw2g6fHfrn|2n!bdFYDO+?!9tcf7QP{q@@%M{R*DThQI72RmND+XQ2{RM5pJyl zUKk#3X;&igeHiA_-&Y-uJKHyk?vDMp7!)AX8GL}{hAlM?_g0o{aSrv{+|1=k_16>k zqNzoutP&`^R}T7SX$r?&s%<|ezgC{Mn3>nuBk$C-)#Rm)>xOG}RPkH=^!6TLmV5I5 zHp?Y9ApCch8{}%qNuIp--ENidtOxpimK&aucH8B7Ifj+~?~t3TS`F&AT?(i?i22U> z1;g@%cB_NU?qkAL$`nhv+40Qw;^ZOW7!;?`@f$5)8Atb(cW)KAU@U=1hUX)mwn2An)+=+!UnN&%EEAQEzoXB zUuOqo$#0ws=~AZO*mPv!cwGuHN=_EDRnzpyr8W8PGe|#a=1gFDrWNy zvu%pfbB~Cr<4fDj{tdlqcLIEWQ_(;v{1l9}XYa2 zm$b9c{HSdPCM%2W{oa?+`$InTBM17g)OrtzGn$wDsSoI7Lf;RPzChM-5rFE^e5eE0 zE1|1KvO!V+{1? zo=`I31VoT6&6RuR59`LCc&Tm7L|g=c^o_4A-$^113bF|tNFqlUbT%$}RN#p@pLTRx z+v%!ZkvOn-q?3ck71^9A$G~0i#(j+%It;TZ-zvv$cfIcsEN zK3c|h{>OR{^5JRh5_NRK@)-}t5Yk*h? z+21@6!~?R!{zbivFSc>?bpiHJY1L|j%5nTo^qMbB*P`Zj&FT)= zO6-r7-v%t$C!0XB9Jslk&o^=5;`8*zu+@TGQlEv@dGT7XvdxxG4bFOY#>3O(6^vV< zbJ0KXa>4ZC%;x$G)0OMoz^X3(!S*>c#=+}Tr&V<&#JS`#P+6Q>If=i8n}n(EbpqUb zn^%$98|}$vB*_oEuX$NdBra89x3FmapIjzLC-Kx7lDSR{8x}|@PPUA55S*v@`%YHz z(|f5;4C715-ZOwK zC;Y-i6I(BjTfdXD*%Iku16xKg2LSs`p-ePz+N*GF&Q_DY&92-cj@$npoOfEl!2y#L zwiepPh)8ETEc(uj4_tLFyl53fWD9wHX7 z^H{CrLBb##tMRp_8|<3zqnCvoohzQdsgH#``x2}!v~Ou-1*Opz@X-UEXX`*ZdFmO$ z1lrGPa+4jj0?dxI`@bPt^#{y_h1FTNBx^`oG$|+!i&VAFH%uzEHddqtZlS^<7hdy5 zZ!y0Jnbfs!e8D|7c?y53;b9L~u514k-e*9%q?=Nk2?W(4SA;AC=^0$tn4N+q%pYCo zU$WYSseU!CVa)H}KAM(Q8XV5$zacn4Vvsz{{h*;j)JSAwHTgy0PcY#gYR1#?+=Qa* zSU*kID*CI2Ds`v7NIT!`jsh%(&_3DTmfPd+2L#zpSDILTJ}WmjgYzCkV$qs$U!pk@ zdpeT2%~y<_m6ADJjCI+UU-%m%33m~D7-7cLr7lKFgIB6&1HTf;%2#72i2Ai!!3%`G z*SSMU=Rcd=L`8gA=sd*7#<#ZswjiAZdqUk!1S>KIVul|Y4h^W1h5OX&NUo@xk+!1V zS3~*S%D8;BIf}`HZdvKR8A#9zPWTCTIk_)`IT~R<%U{r2aGAf1^Z8E#{!qRGogs}T zPJ~W^Er|eRV|kIID}6+FS`q=y(H&$zOk}3gMW(k@HaiSc#A`m~^ejGNWDAJKdTaiX zU=5FcG6Dav)$Avh`^b{u{S_!zUaSByD(z3%X>w!Zxnl&%BW*(oC=3Gw)QRfC?j-(F z6m_EJ{FemOGo%{9k?W%JBE=C81hO_D(6JZ;6_f6*!xx4FZD1Yr$sOXZQ5>ts5nOnz zoy%(wdUM-^RpoeMc`Qgj;nVybZw5iU2@kwNa2-U_vVUZ{&k1RMtXodDYG6p0Fl=Dx z46QmHVs2K}tL-rNgD)wc+h|Mp%5`><^Q~K~h!K4~2cjZ)P{2r+E9|o=m@qc$2eSrB zbbZ;x0t3?_xp}|r3O6nPY~&2eBMRF174QOZX{dn;US@co>;lxYNz8FShOhc*Xo-gR z*VoBgr~`~iIu)B~j-N4%DW>OA1X!A!-A0{#>b=38*r_=~Cf#kmK)hADe1MXFyaa!2 z9@9)(88ELHRwj0TCgV~jju2IIDG}~5gX|So$XFox1Kpxl0&91}_5;zh?|rNY1Bu-% zo3be|=(I6 zeqf}p^pZYEBa1STG}&dLobH1xrmtio3so7()W^dH;YeLzk;fzQef1f$V3g-m#MC3D za5blJQ;{M1Pe~dqQcv)(p^&-Aayat@rw94^&(aeF#hSVK%3CXemKd=k@I25}Fbkzx?D3yL^QuD}O-j2B4z>jjf9)}@ zi=o2eh!>V#R$Tn#69M<=C#EKhg-@=ZKsn(Swu3=S4gvHf?DO7<(b~W)5aqM@SBvMO z2U06_6ue{PEeI5ti7i5!5R>PJ(JZn)1xqznM zx3xw60edSaQBp-skRdfoW3aT7Z=_`BMWETt8*0{?AldHcRH)LsDg=MgjX!ON1#W<4 zv=}7M!|uXic8GOFLVja*d64YKbE@hOd4dbh>!clf^SH_ipm5qIg3|mw>%PCxN0~Q< znI#R@ePi$mIf($z1R`|fMdvd(08csxa|aKS+Z!g~-rYF`?&cGp3vGnO71 z5wsvyZGo2u0H~-VA`bo(pMU-X>V7&JsRi+zn-#XQ_0!?Vavck5FTt*7hZznGqjxWn z^WOn{9M?@QYZ>p6gu^ z6xig0-+_AhCC^{R#t)so-1yryk(NG7=wPqn>VVDiPx`jz?*=lFm(?5$7f#3|y?mpn zcTDnW)-jlm3axM_D#aZli46J-ruJd6Fo5GB$VDwFaNssxp$nata22 zMd{CAJ_S%p|8vu5XT^+UAg6n$@_fYhMY!X@mO;y(1+rU02ehL6SBGz??9RAO23Tw5b4WUSE+yBi+NDdG1l-L~vLT<9 zbM_werQ+W=6*d34ThP?8<(B&;a9jHEsbB~2^587(E*Gw~-;6ypV3U{=TG8H~wMgF6 ziavI=GnB6TtuWPQoCg;F#h2h_f`&$=rA3JCR^eS8p1tUlvqYR;kYW2qs+6|-OLq45 zg}en7RL z-91ii%8ydIcrC2_4$~5AJPH>hW6KtcT*}>bC~v>I1GX)ZWiPFC4zg?NoN9+1a^BI4 zCI0Y8&RHC8m6G?`uPO0psi$-A&Ocwh)nlX1;U0h9(`>S??hStoMsi3;D8YUfmk|hA z%YcQ(-+@&E^BA9s6!oA*SfWtLH`i=*`|Nwp_#(Yg;wRFt+13UVK^X`clXB=xUxnHc?BIDzYS&#L$cNi zD(-$|-%Zo_LFGVz>+l{DjVo*fQ{wNdFcLVw>*R?@Ci^DO4Tzz+^k1~69-Eg4wJ_EX zY_mJGKeomZG|*f+qSh>C(cWKe9N&!8?P~P0FlY1zCFq60xh+xncsXeoR`EtiNCaHe z<4_b*TE;So3AGpJ>Jt71n>0%gyM9$7pP|X!r70`(*8F~TD<5qCZT1|Kf<~8m`e zqHh!aP+9qAkZjO?w?^_&8QTCQEk;e(W^#N6mrho%8Of3BBlVO#%&gSFfGQ^pdg?T^*mCQieL zgA)=_Tu~)aZ?ENVeq2}%jM-9*P{}y;L5B{EK1BR+4ctIzI&<3=UdCTJi@l|Ez|SWw z(>u=W$G|C%o6~RlTw1$?iofQBIn!J-^sEDA|wKXo?&7auE$tl^CCdk3O4uav}rt6%EVzhuhs@d1vd?xCx z_6RA%{_SkR_G|N)0E%van*^+biW-XsFSo2WkTSVS1VZNH88$KxUZs61FOf8xpdx*I z@Ha6S{bH!fLljStN_S+M0&nv(HdZ)4P^fZ`Est8=n-`@ERR6!Ar)fkaZ(A?aw zVESi}^B?G|3GrhN$>i^t;e+5DYCf2|W-jwI}E3}|E_G=Wp4FT;4f|p z7(#2PeTGATD(WUCzQUY6<>A`7)*x@;;QEN*I6z%Kzba$X)@sMtvj z{yzqeX_6#vodSpx?!kLL%%Vkg7GrN{D2@-mC?yrz)RTqnwJlK)=H0`%nkI`${U@ci z)wMqDH`ZJ^x6%#PVtCihXUvlNNqyhIGu0T?Nd*sIA_IbWfDPy%PyP9g>8WGiaDF>w~M(Zf}tXqiJzb%$<%jaQKEx7zn@{6 zG*?&t&|M%2kjat(cDc7WP|Ut4Rzv2w2i5X}NY}@_raclTt#R&nJGQH-wFew|nDiW* zKgN%IrdmkTj<#jlXYd(bSueb}n6XPGj>M5zHu~cAk(~?YTc6$`EsV$6VqNpOPeM|4 zCEBU%x&7Rb1syJ4N^V21rZ-bm;8qpk=zNv~=ih)LWM{>ul}XYxg_@Gdc_-o1UyL=T zSP@6;;YaLgPlVbbr!O8JLq=jFxTBMJ?oKFfOP;=6FbRyG=(tgcHg)B)q}yeCEW2?u zJUAYgv3`!!TC@3*J9bQ2=N)ClE+QkrA)0ecD`kjZ?5t2+%cSjCfuV6U)GBrY?L`h4b`9G3T!3{(+7J)4ThY2=gG+V7Ncx8Cp@06 zQ20@VVc<57ETL#D>S!X=`Uk#@=?Z0m4N1FEvIUCB>&#&$36A#jZmoXw7LGUN0_hM_ zE5)hP28ui3P&39$O-2O+>>Uv+eOKdg#y64nZ`L}R>x>yFV(06PS7S)Hi@vl3za+XJ zehy`C#>i^3)AOejlzN1p)xz)Lc?ZWX>tBgmFL%9q(idAU{Yc$*OymD#j}{RHF7FUp z+tSsAj(DxmnLd1YL)(@u1v67Q`*FpxEtltY*AQG{AtPt+)m zt<@msb~Vra8j=H#@sfwS%rjU;HI6~}%LrVo zWkJ(XaB7K`>P;nh|Ii(Q!Piurl07yfwoy6Z-fPyL_e^onTz-y>K1mT=epXKv!o4fN z5}9l9u#_fHFE=lc?6OKh7z z)d8j@wb~OtE^}0IZ@aDT=g)-()cG@I6{f;=M|ARME|VX}Bvmb33OqpUICAEz>HVNZR@rX<8pkcT`u8DN9_QGrWq9 z&uUzESfT_7Cq}n>dRBD|M(bsbKThe!q9YKj@!blxuKzI6IkK=5H-wF?U!(td6AH1)16xH{07x8JeQ zt9cfFXoL3X$4wQO^#G;Hv7R8hv;?+6WRv&MtrE+BL1-(Lz1{U}fd$99IPUX7aycH? z+i=&->Af4RXKz3EmoaJMsgr)a2TqQODWP)|ogM(XsyF-4u zmZlYRt3medJdxPjqLjM!HcbK!HfEd!A^U>`q;!L8h00N|u-YdBcWXRGORB=wxmmiK z+8tYHhczD;u7$vEAu4b21#2jrRXkp*9EOxIZv7%v;M9 zv9g_P=$n~GyoavA@YpNDuGtb=Xfj7@GrtzA2V912>?h`$(-0GEz-H&jP)g7-Au3F$ z2O27vZyLIzZC{);#EWj>1>r&LX$3`#ctHkWKo3+Q2b?#j*lmlEDJJAqphtmQV91Ri zAB}@Q5K%znNxN}bCxOS1g2u_~lAU?tD>tsXAX@ z2J844#4OQg`AF0?z?Mti2I=HjJ@M|)upqzt>FZ$uC$=PgeA+9)md8-cQ}_UD#s2u1 zk0eoiFwYYBWb6#NT}i>mgKMg+UsSi2@5i%Ge|n?B#__nS zz><}d>}q37zY>&uOTMaS+w$TOP9750=-|&$7Gi4;Fbd zv(Uw+s~R5LOn03Q)sN4Us9dx++l`f3iuxy)2ai?KisLeJij1`xwnbH6R2W0z(M3Hq zcUjd}^sWaBSg;7FGKIvf>%psGuAO;QyN+fFomJ&qc4lq`ZDS(=ZTs_FW#ZvAp&r%- zyTOIheY*yP;g?Bg-dZPGqGBMo{V%1lSO=wFct6Kj*Ixz9o#t5Hwy2)rAt+i zyCIek7BU&?c|ny=EhS&kuD}>Oz%;`q39JX^huvxq{4!SP=tFr^4%uC;w9z2MAk3#L} zst-~%**cW1wT3JgAj_aOsH2Y`0Z^vu@GJmpIKolEDrM~bT@eAVP|;Jx_sCWGQ946qZ!r$?fQ;d4K%V+gqeVx;#B&60ghWCKkXFSHhFUBl=htvSP$St z(iU2M-6Y*wiObNM8N$i})XsODor|7&h)ES*NmhTlB#;TVX$&OO7QHtRuaH+LXJa@W za$CZ?sOszcVEP05ty;Q5_LTi$6Pi0|1ZOpQIq|7%aefo|)Y zRPsip%I@)cl znm4-$iF*5v7s0MYGz{m?Wa~N#WCHqEN5Xb08lzk%)h94THvzq3i&v|zyBtfn$_E7`x!edQX!A*VbB)S-W1jM2Ab!3=uZ7CARj+2&N>%e@G z(f9V34OG8fdp*G~retIujK!Mzk8VF;oP(8OC&{?f6U|8tVIqiZs$?os+L?OH+gS4(o@x&w}9=zHDw>< z0updlIRrX>Rnkuq*=UE&iX1!z1Ovz zf*p{CaomHj&n%p@^p}#|5co?VBwb-CzHA;k*nn;M7>a)eIknA79)c9zSfW^X`ITRo zR4-MGqR30fBXu^vc{~uF33-Dj>oOK8da(MHUrYLv| zHyS($Lb8s+4~$A^j8ppEPCa4p$f)_ykQxPG@9Q1Wzg}YU20Zx`8VN%B!bNY(f%O4t?Q7}n)vF2~ zs&8TSFGG!0qY~JeJz+J&%w(x_)xSWwUPDh0H^aw3%mD+Hs9M5^%8sJ)4WZ*uc^ zsg)|EqWdLR^>{+sX9c}=5W+huf)pI#a`&WX;$~p5#ifL@+eumuBtGvjw+RM zQ6&|Tq38mq(9{P}@xVqRQSe#|PXvjqodva?)>^$We{C+Cp#wg*oB%G(^&P@T>J0RC z*=4^=4|~05qQTzKlc1AC5obu=yHUo=mPO@4)=n=kD>zszU?I{M^icSrP?R zWfgb@6DwG-hAfA< z^tSz&etWB|3?*!>Nn7ScfpqC>K4mL#!%)LYWTUE`QWiVJRLlWT9(*T=Sc)3WXMIDH zI}1$GB~;u-z_|XRZ;z$x7tx+=dz)+L%bBVT6VQ`w(ag>>1!P{aGJ*>e%;na&PR?}1P6v8K(~?7Bil65!}_ z#4$*!zE#JRvz?qRH%}sb=*foF+!%k^tMkUzX2JtbkM3-!D0+)C&ITs<)pP~=q>mQ8g*$W(UV z!-sa%LOYfKRW`b7PhL%?v40{Z6Op@aybkk&HR3kYO{|AIoK|V%7-a7%TV>W6c zh3w;RsGmi_PPydo@0f6bK5 zq?Uz6n1`Ky|JI1pD9;G0gIUV^ z+SB??tG@{x5Za$IV2xVi(siN2Bzb4;etI!~ipXZ|+^3tmZqIsY*MLTZ7vH;e7(LAG z`G#CH*{)`A)~j`~X(cX2LR~qSa8|O|95wNaga0{3h*k8f(@SM|0O|K2 zc5Kk2S@zz3W$=WWG|H@(nMboc&MHk;rxqTq@9ygGlh2B&?IrzkkBuCVx#WmHeyeYm zi6&m8G_XK9Z5;_c+!*+4cM1^wSHBZE>&Rb?tG4 zgV9RR)I)Tj1;6~W2*cRJKM;|Q$qhBDAx5$-qK`VS$2*tyWlnlMPnot%;|en&lyY&-R1+#8*YR3` z>G+@zJWI>kGKV;?)7$h6ZHV=0`Sq9kZh%FB-R5vN+~kp1>`|9G>z3N|NGyH~JyArK z?Lex~sno`^s)tanD=adxHZL`Nd%0X;uR>1;|L+50WZjCQGqQag=bp%i#j5WZ`Qnb# zc%WLx>2~8v^WSLaNo0u{hG&Bk$4_LZ0x9H@BGKKmMqUuu6dSvllLgIx3e2p{6_xC9 zIa zw$Q^P2z48-sGYz`b~?r16-mn+V_6bAATFoSc^edYWMM7mfn4ShmVnyOiz0{{3w3~| zYB1WC_Y7U)__XdfoAOucuk#0oNg0EUbWpQ4W@7gikoKgnl-cbiqqxDBpR$!eC!zZ7{;@c5qxDvgnuF8&%NXLh=ka0^* zTZo@Sw~gm*h!U8ZvFE&wrxyyTqtx>@Aw-id_XcU$kL;W3WH z(cl;J3NRmElt1GYlf8q)uq!>oZK$D7C+-;IxNNW2_WuLB&PY_i?Y7DlCz$VJyxV9_ zkFnL63;L1=_>2=IjklQJ=fDbGsiwVBJAc)eZYEYx$s%E(Yrdut8;NJZajLHeycfv1 z-d;Aq&br0mH`Fq$ezu{#vl4mw{2*)gT3Q-I>HRPv4Va`IpJd0|0BZYFW2YR@qjg77 zB3SJvnNQBMmEG`UmJt(r)^feGf!O0_l?dg0{)v`B9`ZLve)aP?o@x%7e%}l9VB4JbHmhY`SNS{1dNA}bTFPEQoSHsW?lvMB zfAx%bSuHL+82Qbqk>%_(o!f%C&~yAg?=pIN^e?Z+UDFOn5>3RPw0fhIwn@7XqBq5r zdO8^?WxN)p1g)ad&YGGUcsxHu3c&!-fJ(LMC#Z`vtE+vLM!hL(*~UC2Zy|bphJGue zKNtYhgC8Qm@1i-G=>G0bz1{mw7#Y=<^!x-&4F1*!7q9bFHT&AnZy>5KMPLa?vm(${ zq_uTBUkC)~I;r$C7u0!MjCPw9m(Oe;@x&QPDV>FeI*Jq1rZ2M0zYDsFVe5?Cnx2M6 z*C16IP&09dR-Q>td@<*nmV=e?K+lSgBYh0;HtIPw=XyQoIRi1>23rj!? z`!McLe~H)8nJF!<>(}ESW{||JcQMORYaT`MjSQjw>AE6|G5XLB7YhU*rw>Xjj~bJS zz_2Mq!nfi|C6+rcuoPfeP6uFq>eNEQzU+Oa!oP9Y50eEHm{=gYUieX9dgJ~v^LwMP z=TePHopy>h&NA*MRGxstdF;4ZCWuphP(jMoM;~+V3-$)CK+O-F6xyZ84@~lIJ+)3_ z8nKhlNez0K?0Z{x2=#zvn}LVHDwu!Xo#Z;FJK?;BW_#u9OsT`c^y$Xy>ZBm=_v-XN z&R?=JFVY0`33RKgQZb<2us_a;WJC?81my(x+kagW zUog(TgDtZ^Q;UM<@*E+bR#RZYd0+9Chp8)JbG_NZ2VZ=0Wy~3_LQ(4AOg%wPTA_c>M6*9nSu9>2I-%@XBv$OYj>b^y1Ld2G#nBM->{sPFZz{$Py3 zP^|b2Ek-4z8t&6uYi3G^eFdR;P*S>8)cNb$B$vDi<`=~rp!k)Tt+}+YEgy)#cGg^U zg%_wYi+5Qmg<7&Q`-S$+720Ysn6E5n40QDfwNav;UNvFlG{-AA3+P{37y=uhptkB z)gihjM`@G^*R6j3pi^J=soU1~J8}Aw zOrA+$4rN_4RukQrFI#0B1=|l=Ibi~_bzCFZX86s6*og;1Tt=I;qAGdLj7|uL$sk1T zn0-=^EH!L?@0XUmkzi{~tTW9$1%0%7?H_am!|9lqul`bx77w&-O@y^3)1T{+=Hi-M z8J8aWvHy${L~w@(ad5_ZhXbtBvy&l>^#mKN(>Jgqjn&))&SeLsfx0+jL?9b?DDw>c zNR}&>+zJqoi#gp2XvqB?SNVVgagOS_^}R)(#RWNFc@e!;AShe^gadG*s*(A<97EaK=M5a7BURt60K#to3Y@c~ zVT&6eRT*ni=TO;6~mpJ%f&4)`fkW zvuoR^Zy4@-13de{;S$hfbI+-d_S~HPV&EProMs#z{hw$_9;>m zZ&*YSCVQ}iJG@Cg|I!iZG`no|g=R+25G4YdBZeCw3Eh3>)Iqs`-1o=QWd#7zs*53HFSb;O*g!y3uhmEauS}^z?-zS$1d?iV7>~@!nbCKe!;3~ zf*+D9;|CVFu60v&L`~Ui+e(?Jg^Wu40~N#6bngM?Pva04&{e~L3mC}XgDXpe(2}MB zDs;d{^9ZewzJWCL&F|~`WquP*+`_ zVo2f_5G!-JHc~Wb*WQA2TJqm-PEPSu>?6xB+K9XbL8#9sMRL9ojwUQ`7Rrp<5r&4LGMK zwGpf_TYoE8P8-|j9Z~kZKCi8<&d;wUZhI>B!RArdLbug|~YTEuz%h6^AuXDis)Qv!2p?SX$cMVA9E>huAD#2%q|Y>^=GlK#iIE(mX(SZEt*n^ zgkI5=9pmiFgqyk`g2nUiT!8in?aAqj`OkUf9V?KZ3*aeWHwZsuQzjE<%61IjXm32uks7>6Jr+7*}ct&DoICx7m?{Ojv3XATi8c};!@ ziDb5w4~yV>CTc~!scqI>(&^)vXS zAC31BP#7%C_cMdvKbsw-VBQkK7A{Uf${HJUlomx&gd&S_728(!v$0|mPWO|+gVvTZ z5fyjbC^eZBG?$Z1!wi&VNhE6%t%p1+1Zr;iT8|b|bwM}!2n-CCoXcb2;-wz2;V$~8_8JT;@r8rxx zhq4i4lAVaadTefpw1ZCau}y?v_Di4@_Fu=LWt8^w^B2kVbbj>q`~nG!ExDLI8f74i zWp9G0`qOYve>>RK8(ZL=yY9e0!Jj2g``0enhrGUS_uwO53x0wNZ9=Wh6Z89wP6$n6 z*!>aX;GM?&>b}GXW>Jt()X4d>^jf>-4odPoQAsrO2e~)vQ1nC#A=4jab{3l2HFBs- zoo!A0E;n*4oi7^Ntp&?Y3JVuz!iDlh0TUaeFltUdL2o_~)Gx{n=)$w58q!FKUXGtq z>BTAj1b;;25KC+{q$OBsr;0Z5O{`iK*jqhG#(#H+v?Q>zlw|Tkb-huptkFI3=nAF> zy~<_mis(+YwH8Zb4U7=aE;b*fUoEyBQAisn9VzX4O~FpCn;=Z!LE?n*vv9;jR#QcI zuihJ!$q!w{^%1vhLi23{>||nB5%tf!q70%zv)JC-cHRcN{s=laF4FFWxF5)hv?};C zC8IH|*#Ax@9sI?^z^@+#yEd)B$0=b?G+Nb++gADI&prj=xf}9b`J0D7>!&~Kjq!*S zjxPeEX2DVo<@_}5^Tu28y>|Fc-wOJsapA+!2&_}xxst?fJZDo6n=gB2Ohzra9)HGv zI)@s4h^@4DS57%oZ>4%|VL9}Rhh`JC$ODB3|uLV$vja$W*k6~a$ouXQX3SBVM!6A0tK zkPU1JMF4BR;>%&lC6M_gIfzXQQcMYI>Cx0KP>>SD(oN_>z*_P_vP~5eak^60y-mWCnJWuwpIaV6Bq!ag>gt?}DOlmR-Z!CAG>h2d_F= zl72;q*4HH#VjBwTNjdg|vi}j_TSfI-M46JrG&oLDP&K?UKf92sEFc1vqU?gA%!wj@ z!#noaFz-PlSq{qii!f0%5K>zlPaFIerxJ%D6~2&mg{^*nAPgGY?s%;XhdaZ3@E8*P z0s0O|8%u=rK0IT=10M#}(xhg=4w6UOizhq+m+wqjjvW2NzptJAy6I^k2a)S0aeX%YtBqg0k`CnPB?l?=pqVx>37qkAh?=5xR9m~ zB2$w-8vF#M_%RBCDd4e+<}nECy(t;3MOpaQ%*Ce3HJAv0rmWIW_ zLa^j()3$~FJp!CJ$yGwVcTtyeLWNZ3UKk2Tk5htsDdl0sw-lpoj{SQRuQXl zmaC|c_=_@aWLQl60F;lmWpB=&I4pmoaS+JY{0TMNS)!tMZvontl3Jebd*s>jZk>2t z(wgHog&)8yECA;C z_`P4>0+y1%*Wgk1{00{I^{DWM3UC-@{PWfBK@f+;zLAhFFF)SRK#N61Dp;&4n^tYX zIXrl&6ykqY6s#fUpe$%1wY0DO*n=>YDz$R75GJ#nuDJwc&7@ae?wa%e*!UNVv+`?) zGx7UsLj-)EFF1XkmV5#&&?cn<&+mk6_j7*Nq8Ap}ttyn+&9 zM4$p_#o^Q#SbZQ+uQEs{E~-E@6~i=T3#XUNu#tsmPLS*%m{pwYsN;HuGe{E}qLuSg zhGcPnOPu5oBuirceMuR9dCv3y_eydDP|hF06b$EDgjhI53d10nj5$ycutF?O?Xh7h z{e&$H()kAQ^j3GjX(|lUDTGEbls`$bhY(zQGNXa(S!ab%S{>2)BJfd_PiAz@ZqfIT z$IEX3iYd2#UB`xdL}Fn+&wsak?fZ(xxHXSDaZYQXtgZg=!I9J((9is#55xmIQX#OFS@xY8VjT~BMnco$-XGP{&~{z@oWxm3=PX)aK? zbZ*Y3k@z#Tc%L(xm%IT`E5|KaZBX2`(`BtYIwVyG#WQ>;8i$((ckV5?J6Zvf6TJ|p z@V1K!T*Y~`fiRWzIw)O1G257-AeIXk@TyWvDGpcZR=MsgOj(oh+F1Cnpg-Z&*7-}J z20u_bf65u>xjp|6X0q0I|S^rfkGF;y09J_1*-fyLH*!fx|Ciywu?fvN>1V75#BM1 ztPkJF8b4{5H6Tw8LncU14pJG6Kpvd2K|pU(ZaYDJwZ@(a)^+6i7fk=ttZZg6NDt_l zcqv3K2~JGlMrWn0==dCE=V-)6XDO1s_#9v}_339=4K>wLJyT;p)8XbgSWt7k(0b-< z&tydjXhwe_W_Kj6>}8d>@H-kpXYghsi(w~A(Yz_#xlqo_0VxWZn*x z-HriE3B@$3w!cNxlOCc+dCnRRXrD5xGvS31u>n;h}E*-dWP5$J_9=*?c zk-rnp$dEp%DRz(`x$1hU+!aDlyiXm1ZUc)$1pnN-cyaEa;{SbxtgXVS{`&S)feFoK z$Fd@XAtadf#|g`qws-YBL~05Tqk;g%o~?X=JeOZuP*njw7b#&B6(Asl-!-Tt%8Xg~ z;B^h8X!Gq?WH>6~B$EnjXI)uA6{Xs(^{I>M^!!nkXcIlTX7hHFLQj2hlk$x@eGxnF zl+*QUl_RNDdC;O#(00E@ZFtIEGgWCxx*bDq+l}JVGVraHWPWHUCh%p>nk4ePZma7N ztD3ikIO;=tlsPAk=pgZp{TJ|J-Pu&`9NE4yG?PdZa8rvHv6Ms`?vYqqLSy>e5m+j3 z@{LB6+|f;FZ>T;+BD$nEr=uG$p5bML4oe3knc5~lCOB7#7~Lj$FUf-I)k46b8~I@U zLH8#&LQvXGz{~Ya8B>G&${MK3b(Kz6WUyuUB8GxyHjUV&CexmQ7y$af1>56SSUw!{ zDt#o9{_W&LX3OsR7G^U-kHt;z92-UQh3z#V`L? zPhWD$DBH%~9dvZJFR9)z1r;RCUo-}mFI%7srK-)c7`VFxZk)y__XhJGy8|v*ZmcJP=5|92+>B>59rE6 z-eRW7Q+aheOYTgU+$o>xWwtTKWUxx~QyfHj4zA9Y9&GFBX!&=l&4%1|XrJe6Z0nkk zFQv~3Oafg04N(u7)xI0LWB(*I2_6#*V~7@%&w==SeTpS(zJ(JCjCA(? z%b8=nm&+?)D%Z5O2q6iBq>e1cks98xyDs zxojUM2`#xMqTpUl2(u%_)l%mYX-UG<{2=hHF=f++3^H7)Gs0qmTnasI9jYhHUFfII=5Q0Ipk^;otYBULu$UT%$LK;R!m$u+T-m@JfuTy6VnYNa&%SlN`9>ANd&uj9B*g6(yzL7&`9E@jYeOAa< z%|!A&L`C#u8kzDVBr1Ghx>E+>p`IfNXC3X>*3Q#&FfLqp&u@-dX%}#+p|KpY=USBE z7>^;N6$FWODpymF)mtMMZ zkOMF2v4vWoYuX((K`y$e+DkW~cfiT;J6A~i-Q$9|{7{bWGYFkc_+$HGB9*O!{(>84 zj24d7f)?F)yOYsyXJt!b|I8armC$M{iM~&1ocu(R_Av5YY|(~q-v(3ffOQVEYG4=4 zPs}}!TO_7N#i%zrI&@?va6CmVB-|;%+0g!UfVuDsB6$7kxN}+_NiJP-kigwzbRnNc zqG(UobSzX|?R4l20({kZn=qf1n_ttRT6KC4`0``N226p(0ZsP1z*#?@*rTX~8;=s} zu}s-Z|E;V1!Hw6;ewLT8(D+y?q;fC+l!M%z@x}f0?=!CyEs=SEft#r$BBBx28fkm8 z)xK?Iy)}*Aww}ln$&XNPp}#G>jXR{rhKU`t%#zTuM%#9#r_GU zpGQ4=Fb+bqqo)y44G(7e2vuOma6mia4+GoI*|3K66-_Rl4|_i?o>4ss@|94$1d}!3 zp+L=VA8)TOJD}_v`p9_ZM?Es&nFw3?F>%UHyL)bGqsy5wMnk733>n){qK*o%dQ;cr z`26b5MvBF$F-vwXv+RNIskj3!{LHbj6^)RkZDVA4@lP&j}fA+t8;27g^O5%bFvlYC3 z4(T-+MAZm4Qm>anPph-@){?bAgc|BsS)|XtHgKStzpDEKM8<;PXbF@! zEt8C*HM(q-Is32@eZK>3gV>K29k5vF>mBcpk_<}!{8cTuIvJ2Cn0$m+du&y?7`}k6 zNyM{z7S=hiaW0QfKQe}ZKTi!db@_)>-{M`84-m|Q1Sn1hZiIMc=Ef)ivi_G3Ve(Ie z=il4RP1X90upa&t4o@pb0~9?^&$R-ouJi=AC_PJJ|o#Sw3c%kD(x5`oaxSsG-W_1Jxo<`IzIL0yd$cN zBnp2mSvHK(wuw!K#hq_(#i;M2n>VV{ISc3EBNh+;gbi^ChS8kMv)nFl2diy*lU{S7 z{c~Mdz^Y>^(`o#bXjdH_+V)c3=Y=Z7ofPy}%0tckY){5x$NG6$-Y*U_Py?KQ(3u^r zKu;Y zzlym(KNU6P%zdfgn$eFL1kKu;$D5Nb+F?U$2&l%5sidPkOwF*Z_E2nCpE_(#np7R@ zv}vH2Yt5{M~$vl;}3X*o*6a0&MIXY!vuoISkmJgMU!dEIN4Mt}ZhZzi*sB+u6m>zKwrxm9g(zs${o-)*c9( zRe5l4{{kNY2Y#uar4-QzwUiXQl6$zGCA038&3LtfaxNb_%yh;mxz-~XOC79_Jhb>f zbw3Nq+0_-M8zmao#1Cip1ly@EzCM3)E_ ztr(2vXeuH$N|dN&jn!Wk=vhCHiyP#nTC;yoTP8p~7;^c<>8x6iQXW=Qs$={9E@kLM++HC`$XSW(5@iypMuQ6bUI3U`_I+3Zo|6y%Ph+=JB z&*V{TQ!~~y;MUr)8cXs=mjCD0_GscK7wl>z!u>YSMz=i$ANwK@8G*Co8y*@#kArtb z2)n5~HN6rMRomq|HN)oV1ZPBnxGv-_`PGVU!Cl~!neTv3(Nfsztu5?UIu z5nkTYiCbtE$g{x`dBB z38Ab7)YrmZ&ZpcEOuUxg*s{a3Ht7@GSbo*V`|M;zj2V*Ejza0oEs@HBwgso;@X-FU zDX678{o*KWX+$2j(ZXpLXXP~bwr3@yapG?Dj_vkpRy~~DU#tuD?iIGmw1B?^aS{F( zLwEMQtvEXxD}i(uy%Uih$w0owZOhpjomKDZnFl7}H$`~?9Xa%#9Sh+Id*RL6i_s%S zM$yq4BNIg~RVL9MF=3$zfZ8`}T1?8}w1m(IzP_y6Bw%19k4TTI{GLwneiqr5@DWx^ zB1#0|=~}f3YeSzY2npz)_cVKW>mF)H=lNwmYkH`GR2xL~Z} zOEFK~*d>*GYUW{bl|mB~?%=3OVjcYTNK9XVp%Er7ZMoWsct^oqKBo~k?e9?voUf79 zBv-*$RR7M`DD1BlBaC=O29*^sNsU^|sfY{hBoK3<<3Pgsc@n%Bg+22PFBa8NS!5#9 zX`%W5PAhaHb0X~EgsO{Q_hnQ0L#7yfRQ2!3d)wxARue0+bg|Y8Dh(lLAs`^vT9u)z zm_$EqI z`=fgk_vk_!SJ+ReuzH|qtW73a)dMA6lI`OQqnNU5{#2Z)nzJkNOgxAIBN>h}!jUn_ z5bgl5j>r9O!ij%*t<(4K0BT^6n>8Jugt2aCQN zcVvdP096#;EgONKj)gh{`XFctSmLR7AR4cLY-{xltL**HT)?v8U)r#!j- zhJ@EsnAnf-PUI3&Dj4f7z30GEA%nzU01XMaXfQgj4Gj0DtXqTs-{OsD+-pQ@yuAir zl;Rw9nxcb;S?$ml=WVZj86qTkHF3HC{L?uAC`yn|;@R<>Rt1lKlIVC`|Kb>bU8t98Kt{91(0x2Eb$z4)~=ACKR^+^YSX!kSy^ao6I*kqn z3;d{&!AqJbB<@E9%+!x@33Yn7X&H6;cj#gZ*9bxSH!4Ig*WWLaLYNc2^iP8u^$<>J z3%-C3efiEHO^x3U8~ndO%J{6L(;5^RZ~BwL!tWewW1{{MMYql%Nq85~|N3M)TM&N9 z8JhpD5!|7Vcv2nn4v;0aeh!tOmrp&1I^~=1vOe`4(>Q;B@T<@i+4#q-nH7-nX9bIG z3T@i|$F~S;*M8A!s!u+?Sp+NB_?)@J=H=kV4c-p89d?gxDeZSzVF8;8zbo?8lFa6L{FM)Q4RIADK)j|!i;@}t-N_PO^Q$^Suvofg(gzqF; z$v5HCiqD7d7EjlR@@BAXp04oO?R|v>hDQtARl<4YNP)=-i+3!eXD)cru7;zqEVJoP z4Ktgbh;zzU7O!6sLWAgkpE8ku9~n%7>rFL%$;>K?>)}taWs4ZLe7iA;q4Elde=#AV z+eUuBl0GpI3%3qAiJ01vLu9CiR^9vvm+H%>8fryE{At%3R@Yc`Y$Dq_7n$ngS9kZ_ zUODpJ-d3&{H|4jNXMLg9v{euzprGDTha}U)(*<{qM;1R`MJ-h{Qf8$NvqsCEn9sDkMIHIC+}jWBJObdHa191yWJNI-G=Tn&^V;FKCP}cg^{xU>m5un| z|B5tCy#hRf5BRVHo`Clh4|)JTYEQW*-gWm!zX6{d8uCd_v$KwJobczT#~qO9HWyMp zu^I3oJW4JIm1{c`PvO36klJOhU}Me9OR~mS#U^^baqeW zQJ?|d4g5`%+3H4cRpGRV?{tzyf_<2W40d)M*HMM329b>b4OIeNk*HMwf^onPHTq3n za)S$=)elvaea6V3(P81A?{`4TXJR;}rELQGsPLf($AwTz8H@s{(rhdK%~Twm_&1=nd*@)~b+6f&OxX1HDjzdc#`M-I)?i zgrl(oMM?`Ed`4R$0SP-ah`7k(>A*L_PRrd z-g&X>?f|#{8*Hz*ge5%K=23WSA+RS}a1f2Y01mY$20`mcRlOXf`bDh8;gM4krYcH32)UKm-r+Ev`jiOY~%%o zaDmaxCWsogTqnU@7C?a}iErBtXwwI%S=?QDkcP^Hs4hXf%6dKmU1OJ)BT&{rU8ZR0 z53+Z@dO>yQ-)9Z=glk7WvJi|v99shj!bu^pO(YOcWYT9?i8Vt8Qw$*hN1%|54^AiJ z?m;z#t|8YJ=q@?}iNd|*sJ;psb-q$lXH^!?_xJKt+2P*U?2vul3TVZsKVYxM?vzXV z(3~_he}GiW<{S1mkPYQKulOi#is3Dm_u53u_~tuLRe3zOGS}Lm70c80UFf4K`M*cL56Y*g7=55e&+p zwfK@!EKxNbwb-3Qn5{$Lx85OeMrL!n!+om7Kew|jmq{n-?(Rqah*rnzJ)ifm(Eu&f z)uwCpa=taEw^Wqmgmsrx-sW{_k!6e~nJF^88pt9VPp0VZMj(q=EV67q=+XoULfJDFtJ-qSUB+@dvW_rARBy@6H4aJ9r zh4~H*=N4X)Z1j6oM1i_fDJf&X&nM=isApo-RslszD0rK&-4xtaPr}s@EVVd**Lsj> zHu+%tx6QWbquKTj&p!+BQ`O9#UK?()Gbfw)f(IM-0I&=6|Fo4z`)L-2Z%|Z7I$O^>yfjqbxn7=sMkboBRFB`!=6^> zPFrEu(b_ZkXsfA3l2(n^jAJL`;(pAK2t1Vs``CxOkU9}EJHNfWX7jHT_c21R#Ox^{ z1N+&_+$me(?ucWrsr!xQR3l11$wt!L$K(}k)mHV}+_C0j_tJu{b~r<%{TLLni&abf znm`faHYAU*Pf0k!_yI^iHJlz9wA~O*S+U@c5ltb0P%LHG!bDi&%vrW>VeJ)QSD4f(-p8NyXP9+f!9-4c)xi&} zS=e*t)?A`_@|k1Uo^+l}y+O%A$|sA$%yBq|_>aAdFN6xHr&UJSvYpZe#4vv-9b|t4 zR%dr%Fg16ZgbjQR+nP}Ot@Vnq)6`BcH`wYQ$rKMW-ADy&=$IS`i>r^K24ujP8Zz)0 zT zhvEY{2}rohJ$877ZiT5GZ)KOu9biU2&68Uu1(efDh&!XXVr7hPbxRAwC*AJHdJmCA z2aMZrdfMePu5m`Fvy_^8m$!C*t0HVaE$!l?`_y<;NEX4i@8w_NxtV+LQ{F3)9-Mm! zFu4zwp}l=+>z#a2-Z9@MJ5|Zt;JS^^UQ&^wGEG*|u%lwr$(CZQHhO+d3O(+qP|^_xr#1=61SMNv%p&vOcZ+ z=BzoNF-EeYgA8I!V@^GeL|ZYs8w_NraCM^gKrx;vjq_@Nprv^FwFL=|y<5#U=kdk7M%^1Kq1zRsHZ$l=Iuvas)-8&8_|HNG5$<9K1wP zB_4>oD8VqKDtGZqLW>Jr{+jK?17SY9fzhnF0{V@#-jU8M^!lGloQke~x)h=#8n*2b zdF!eb+6HBdk(=J;&%(|L?BUu{-IXp&ilj4=5!D7_dheBY(^?1k$_Q1I5d=T>%TV;+y0V|PZQnzq}{E{9jFPv_djLucpH zdv~v84{se^_D;*ET!&c&LvDYND*WWKquESH_J|@fNGQ5vlTqY(fT)5_4hrcRi>O8$ zCzbU4LX{@7^gLIU=I?V+Waa32HN6B~x#b+a1QjVS%n%SliKcs^JoiQjoY2PkNL9EB z7KtuPI8xntNu*lHjt(X4*3(8}%O?SMR`ZQ51%pOHEr-hC_d6F%09+uK)~yh2HzA&M;sKzcK^ zWt(-C2vtBK@cMyePx)B~g5*@Gm%#^5JkRVK{5)CYv<9_X4Zwgkr>d2nIHhhWFxW0h zdD6rw{y^r3>+>aAFkBm~cX~IiDL+hmi+@GyI*UR(CkX$~UKf-MW1L{pUl8lAU=l~_ z+eGj7)vPtL?6$SZUboExpF6izPMGcJ6z93PcxQ%Nxz1BDiO%}36f?E?krECl#F}y5 zxP;0vI#(Y0H3uV2lnyxX#}*=XmVH0&9Nkzqn-mX6DPnLr03nE+fxy2>=J*U>h`-=T ze5{L48u#5~<)VK45(6=H&EHEe7b+@U+1P z^Ysyu$z<#xS;ZK57iQ0Tpn<9Q8Yxz3)g+{>lWgFmOIo4~Gq2!n~Vx-n1X}IUQn>eYt4HBmc z5*4b_j2AGQi?CT;&rwXOXAF$QwaE;ochkFlNSHO1-wwZ!F z7n+A=#tXBlnpRwJk7aqJ+G>5j+#x3&3)VUPlIcmL$H+`dSv#wO)zam03}|;^B3z2@ z3K#JniuhEi_5DmuDE|B+4hsNDJo-)GLiIwMS;sfjdbHHMUXh%Qpg+gd{tSpSMZkvl zlI(JM53!x+iJuIkh;IkL2#H)Uxg?mxWN`G8jwltzC0cLhdZ^1$#Xme6 z>Zcj{;tFTb(;eL!)?{tfW42_x`-Wu#{?NFZpi{c%IGXIM>(7d4pT9vndJP{HX+cJm z*@OTir(i9dr*)Sn0GAc-{Av`_|NE4hcYcnKpMP}HYJQelxKeX`%E|c^bL=$H$dug} z_<*ZA=ao$3xvZ%#StTr;bqhYy&jLaYqI{NPHaqZj_I=q$90zkkrY6M3Os#M2>ggSH zG&lbhiV0n~u+zJ#qwDjzdYHV(q`MyT$#K@+fkx>~_y>$#+&V0`}1tq3MO?;#9 z+z+(erTe?h1!dEgha9r!GK=%g9UwdK06d6xnoQxg|MYzm`t)t*@)3~p&-! z|D`S6d&MfquA@8K$9I61Gp^2vYnr`>ilf$*=vuUa9DWJyYe2LzOGIjydaOl`Y5p!; zZa7q!kXEB&VgS3BugR}8&Kn_DgEq-y+(hjLr7ERBkAb&^^yefmoMg28ifYCof`u4d zk;SJP)4@&c9rNLuFG{%1XC@o|Gqfm}LMLJj!ACA_m@GJ|Ol==3s-XtWni&G7Nr4%9 z98QJ++}@=wylZ`R+-e&P?9j(0#QVN?I`^Oa&Wr_?$1^t9i^c4I${w6&cXYWx*}o6v z-IV#Z_XNC+eVw&qm}T_lLe=|+o#89k*)uzZG>=p?5xTGpNlm|u;=??{&fn8l@m_AN z_kTY5c2lF$TtXxyzrjuv62CW&blnqW|9l4SG}h8fjPvP@s8-+eNR0pFyA?aJoTmDq z=km@1WdFAm+BL44g1>d{OMn0sJ|K!w&ajhXS*k)4Nes>m@qwy~Ci2r8n=cBQt-(qx z$_^2wL2QKuM;a-tI#wiV8w()7U%_9=h{1tKxkUzo;Gb+W#MQ49L3t3M0%L%KVew~9 z)6Gn3Wd?^C{BtEG_tABnRyr$vcn}6s?*EQb;9K}AmgN>N|Dc^?WEg4O@EfIm&i`e~ zq`-}*EZCDln2^%XV-I?+7WW=e9UL46(vOT{5GgEE#3k_(Q55lv%n8M6TKxO~vy7Xg zVyXTsFv1^LO4`ke^857U=nU+)CT%kOM_0*=NJoJM-KYtvF?Gd`H_RHi3R>)hqirp~ zT-6){nnw1jiYl+`U&EFH{qn77NC3*z5!|hs@BJ{k6cj&-a_{RBj17J1NRNfSs`1Yz z#Pi1=IOz8>Yj~jCN)gM0{G84)$%qE<@n_}0|!?6v2z4g$E zj>NpRvUqQ9=*4w2<$~YJ-IzO`x*B`ldgFQHCoEP{s7fI4I7(vnyJzOs*ie%^ z+@JESu>`fjczZx9wNYCxG!=h{p|&(9ZOG;2w23Js+zaLo{IuZ9cn&~-d0w?)LS2s- z_WYhcpvX5u(dpEhQb%i?3?u#J1TPo7j#^qM6?{?koY#kp;q32eKukon9vecvNf%{! z7psYi5g-%YAY2afxLyLao-J*hE7oyU)@70?ub`IqCcae6@ayY9(fZgI9M_|xf>%() za+z{=*Oq)vbhjjvV*1tK)ZEO9x>k~1%rE4_d>r+DnyO&AV3WJx*I!gq6mes1Pe$fy zB5z0$Fgjy&VaQ6%%;}O_OiyKzLvfwgldZTM&^ynM6@){t^VLYqj%k8hOb>N|MW5wI zz7}Uy>$=}c?7V_xXI>Jnp(28vGjCi;ik+|#=Y{G@(@NCdbjhu#DFlhDx;HE{dgpU> zZ*YNDAXDnQ-3qE%Rzw@RzdBmou(h>79z4+|G@WdaAJ+4%K1K&xOxg-UFgIqcfye!8 zto`=GaUP<#x;uoUCeeIUV`6DqaYFg1f_lye|8*8gnR>Z;<>al|lmFCSTno-e1US zc1_jvtf+`qj~B8VfBNG=N<+8HIb?_a1oybO&^Dw#M~f7}0)@kjyCMsWobkIQY^L6R z{@vEUT7i+rd&)*6cv;>eNL8{bJ1K;l-6#Otkc|6ub6Sbw>2qowia+6l-M?f~x_LXg zAiQe?BAH>_;IQRHcMjx(ZJV9~D0mpju^2-&)bOf5imS8Pz2bjG{Pd7v=dOdm*4VAESo!-3bhB6EADV6Sx2C{GHU&@Y1wU-(_!2aW|OSZqs+SV4TIfe*w_!dVr>bu2M zWvF)))py8RbtG~+j9L_QO?e|#+&`?n$UJ@_e2Wv3pUliuGKG6nD&t-=Fv$`^#z$ryY7gX|56sEsWkptZG|Rz`#D%Oe&*bXBRxuZ|BEO&U*aD% zrWd9h+0U`Zd%TI=ucLf=PnH`^e1WE)&l9CcGJ&4*qX2)3wuu5nUcdQ0#`692D#YAe zRZaDAugF)>I)|EMB;fJBH~+))S*LM-wBU$Gx9L82wLHhS*MiB$!_dZ6xq3^$KskNP z>IO*s0&rU<{8`|&Q#C%xW&>!XW9G=q&3iBvf6m&pNZ87)lBRqJi2E|#0^?OAR5c5c z0OeJ+3X#ARR!XRvhD?I?Esa;c zRwMW!V)_x}VIt(A*CE(AX=taywb3f@zfgRLDQ^T>FjAp)KoT2C&4OSu#qrIGg*fU9SBAktG+Wb+do76*kN~l_XMsp@AMQ zyWqga4V5OTEQ!!7m$NKO(Q7XZ1BitlrR!M~_xvY-vN=aoK2eScY#!=LD{xO zNi(KtR;ppTR?3sfrZSIb02RUwaDxT=uVC}*{ooMiLPDR%mcjxV)%4n4_k4QH1P1F& zL{*%qta+1qTw@GtB(P1`8{T3x^0R=jIC#T0W_P zN0fJ?2ohR$sQx~EZUG`HIB5}PSE>?CtKBOtsT1y>wD1F3lAq%Ppd8Y$E?6VUe-Yn= zKSUsg;}Pcy?pwe{l!5fY0(;5T6U?*_r|u%$i0wuMn1H|49QiPw=2=@Ptf!}4dmWZ_UNRRAS0G*GqKwE;?|);iJ>EGO))KlwOTu1Nd@){>>PBhLRy6oqKQ$}B&nW>QslP2ALxE4fJv zSFWkAP5R9MRG%_&C_*A~=O4JwAM4>QQ?=QsdQ0+rKhPb(%!x$#h7Z+~{V=;Gnj+Au zkuCZ-3MnVs`#eY6VQaskVrF4Qp&3H*|M&#n^&NodM^HN}26_pc4^T@S?CiB$2;69; zEt5jYX}#Tm^4zlJvVi*)Kx>>V?p^!Z>JWnYr@dSx$zh);*~Z$xpFj$B zJygNQ#RH_0B97#Xq6lZvCJyphw4OY} zDM$XJ7!tU#4{+n92H{L@^N~4YE~&-kD{zjPoXVLusm0&Y|GG(|0o^c*vi~+jV`P|k z7Pm~A^nlD-8NvmEnKWm6;N=ZGAhT~$G>_?nTA^wQb9!Oc%d2G_>Jf4(`-&7nhYX;% zxBJr^=0U*>-&+~Q_&#Sg2gc0O;g_rOv{sdr8`wEHDP z?&=#z(v*qy7sKy?#O_!_ubHY-xk3Fg=#uFfq-t^=6cn8Yr-0yn#U&aJ}=Sqbgpy9zFW z50EG@{HJZ1dnr;&x?{H`bgcBI-a>=S3>M+q>WzSy{*{Q6mwkZmU+_`6d0c|JjWZ_H zB#%X%)$!@-{BUCK@JJ_^qh~U2ps(&JI{Nv?Cec1I#nyJYuc}!8zqp64oaz3T1YMKY zI@yP`8@OQE$PPT9)Nc%{zai8-oC^FtObaKO&8)5~zIXH;v5oq9tPREsX}npLMjZ<3 zlyADC6e^s@+jF*ToxkX2?a~`aL}Xx}_lM^lkIW4hKJHCeQeQpvkYBx@Nqym?>;o;{Y!-jOzu3i_Ftq&A*rm~c}L)&dw*BKcHvajM1fUOi=Urtw!>ZS;1wv^3~6wgV|+3-3-q$d$8G$Ouf)Ybolb z8_=B!*t<7e9s~%ISAM871;$4tPk@vVzWUO}#{&?la@Hzt(^myWWXFpF1pWwk0Dx#! z0Py^sG*7MP!Bi?hIE3Jt5Repmm@b<2u5_D zD|t2w@Ls>^P=0+3Q1jdBE*9P-aLJU>iv9}n zkIp+;eFCzK1qR-nCPFs(S}bR%yE&h`4DU0WsPy1gB@wXB{}OGp7t%k2Q*Kl{K$eg< zQW*JK1SOyIO6^Q+x?uj9!+=Y47A)}P$%b0wYfbgsPA&`}ft<8jTJhDcw0bu2-}WZy z7F)(Wr|l3q^rV(>JPpn=x%@*};{Q+j%O1-fG8u$+;>5{pD{`6H4od~D>JW%>N5S8g zI7ibm(NN@ahio{KyyOcWD7y5lf?i%183|Bc_dY*`>Y2v)4xkgW9aoy0x6=iOuzCjJ zu8&g2JzG;QZ$izH9X7s4GDa{)FiVq&eecTg&$49nPmf4Z7*8dr@bAqP@SWDR$ROCXR)c_~gb3fFo#G!kwkX@89gD}0 znC-?nI~GqSF-`54pvB)H8tl>5#rA!FYdD4y!z?Xv-pgI`S=N zN-j&kYmzC{8iDIC!?d$mLK^BhMmw&TT<%mJV_Hh<@33+USJYlR3xmz3e|vn0_~x&1 zQCVGa&XbUEGDIO6D$Xc`QBZmK78YRPZ76We?w>%GEnKo&;A=shWUfmBFJDhCKrc@@Qc1kknuxWeg1d zF|gi~?rDfTI<4$}uw5l{&&>ssG7spHVH2rh>LiC%5_-_Z^67BKbfOZM4XSaMbr(N0;OxZMF1j0%;n$+p zk0UaR%cJGxg+{ssTk!42cQK70e>BVtW?6*=uU0TyZtr$ahn~A)A>?-ClPTma=K$tb zG{eQ%+1}CiCdPL3N(&bV=A=sSKd1qGr7A|caiAyf`*Y)Jtu~54Xr&5m`Wn|Y_r>?s z@p{Q|A-bsVix>FOuC#g2*tfA|ny3-ij}f*DZEN+J&3*t$HxgrwUm!x3G8#L83P}~C z>GzRoUP#6sAExS%fbPGA)`DL1@qK*!X!)ysx#7% zI&04IzPM#Zi!rFTytpA21!EP_4+mGjFQOVnIFTzg;l;1a8=i<%jl)m>lMYLisWikd zv}IK-aW0tYWw%<5R)|n9BiLSsyJ0oAmrD%R)Q{n^(-=(3{*__?T{{te*=>dmXpeWr zMq9eDH?`%=?CW>Vx?_|@WTI~1I*W?ncPI39HnfGpXV!Piaum2B=&==I%arow%-H>7 z;S527kTRDea#T;vnqFFwo^x(|7xLNM%h|vUy1wNfJ4$-(e**Czlyzor#>t0OQC$Ij z#LHYZ4MupeT2Jtcj6~%p%0a_Kh1MypJv||wWpT*LuoZ>@B6J%ay(K$rTl@1!3me!; zwRhvhg{3X*p>XjCRcri77*RW3(|chNCMOWo;B~vf#o}U=22$nb2t_U?+N6(+l@OSd zQei)U7oppNrSYV=O8D!fKPA;b8UZ1O=nyEc>%nZpx)7Xr;&XvO++4%<6&6%ZpOtPyR5MSNOSXAV-Nk<`n<4PB7Ul+tt(!K<@d^ z6?JlHNo~;S=;x^4#&u?EjU!%c!<8hL+x+uTpY8H|$e@83DR^4(IB||Yh2>lNn+$1U zt_f-&G+6jSQc=P}`wt93BpIy&8$q^#58K<${}wy=_` zP%65~VbtRQPp)hskBGuhs~#_Okucvd$JONXCEdzU;I$dbL+S~d)bkL5>H*C-CN6yI ztn0E%#MmgwswQW38KFRB!9@y8QlGAt#D)EzNw?Jqe|!`o>V6*YE8{!VF%o zE<{D!**k}gl6-O!V7k0A1tEoLeKULJz8{RFHv{C=RnnUaXzaNrS~C2XgB}{(y0_gJAw3Zu%i0 z%cpEocC^i6UWSk_#EKv%yH7BfT=2!m>#Z-N|%S_jgR!SYfbY5GP|6^>4{wCXu(m-oBfy8ILg@kXcgCXLu zTkQ&Npqd*Lsm$7SG`X=09O{Q%4mo&}*B;ab7^E4`n-^f5O8OHRWSKyk^@romCi z0v(#Z@<4RKbXCQTFfu7OCrl>*P!Sqh2s`@%$*hVrY<0~ClHS&f)c~B;US#m}>`BXA zw*rUR`)HnvAG^rAs`cAJh{o!9w7B+gyaku*KDE+cP{8wk$JSqcT(0TGt&R%AyCMh& z7APLVe$|;&rpimoLxy(9!@SP?7VY}ZNMEd&0WIVniG|1!k}fCIMrx$<``zw$%hl7} zY>BNEr1=aQmfjvABTXRwH8c{;Fm&T1b=EcX^(R+3Q&|C6K&wiI2bV|#lkRNB8h=V; zP7GQ-8jvaE-cKr`%7kV9BI9Z9>%x%>-2^uo%ldZb?7r#nTUQa94kB!f#U5>CJYCrO*>8RrR@ACiXj z72SF%yTL0hvMi?6-HxpjyTPj_$;cVYG2U>Oib6BnO0c10B&daSSh|YtKrz}FWM6R7AMWMe}!cW!+l_v$JuPU^- zht+>qX7&UGEW9^tt8#+jdsnLR5cCCq6pIV}`CgP;app1isJ(&QoHD|B5&i-n0c3rya>GZRE{>s-9u7_gRfCksO!pwFn9khm+t*pZqQArM|{ydsWTs;<5kF4f#o4UB~4DlGNTM`xcO@*H&a!| zq_d-#5)n-_-cR)?-ZGdAux9%x_pHSq_B=S%y>h=jNa%=s)BE}4=*)OY@7A0hBXrBq zHrF~dI^#T>KO)18D~J`+`0~FTVJb#WGG+gga98<#aPkR6AqC6W`Xc?j@&1ckd3#H5 z=iz7KdQb6ajOb{LoCCpAZeBFbj6XBF1 zweia+zhUy(at*kdnCYX7g2THkqoam|qM?l#FrX`;HY+%K*|g8Y^e5&LGV=EFbGn<8 z^#D`rrHoGT$YsSb(#NGS%*g@K4AUBJc=ri%0g4C>P_qJ>T8bGY6}&iA7%DV)`BOq> z^k3`b5(+}s6B&)1qT%~&TyPF*0O-cHibK*;WHfmp$BvB%AsjAUV0j^?9XvQSH_!0@w5tQ9qUk$=O zp?o{D&?p}kn5OGRy4iZmSIxV==sB0~27eZmHFZR$kNs~2T+k2lNj@54`U~@AAQT+l z5ChtS`z0wvuJx}F-6o<{XsB}rDKucuS!a0#{LT}8p2mNG*PZ#z=kOkl3Z%T?-4D)v zLFqdhX%3fwp5%BSmHJRn5_v;IbxI$*h>F$liGKkY<)bJ6P zhN2QR_jil{U9fC4w@hRQGw(Qc%-|fyqAPb}(P{0|&ibbY`(!sA2)Mt21dcN83XK3_ z=t#xWa8VReEzDOj6~&Njn5FSolv*>!04KVtz>1Ahzlw^;?wIBf(UCHSLD#DZ>LCKA z?je?YD7YrI@6zZs5ya}~%>X0o@Se*zrt>4nI)2GvQOsc zQ3``gj7zF!(lBDdsHUtvycTxr0{b-mbE9vP5J|?g=UA469tNI0ZYXI|<|7wM7<^}E2b=OjI-YQrZC7Vm6Afmv} z;+v!A>3V;~hmT25A$20%V?y;YD2yeZ(a-W!S8y-(S0PjN^oAh=U3mIz4y^2a?X zbBhI}TDnncli3o`;FF^CSU?`&guG(7cjJOTB;$hVSp<0^$(KN`B`S+1GY}qw004x) z-Z1lu>t4Axp~D(ycKc^L*U!=7sD_p-pG`CiM-GU{DddqVXgu=EUxPc-D||>w+yOaw zKNOez0xGf_H#gVMm_H4J$H1)+^-3d)?_^JpqaQl0^;oDbT;?PcZ%6K8Az`fF5>;+H zz8{%84!|q@rE~o``)tL z=D~fFckBFK4qVqu@C}uaStuCk824rLrXvFK9gg;}6UJqb6J>i|7#<{WPkn$b&dXHGkg6fG@9Y zAjK4JthTWKzMFdWePzG+O04NVYIE#@s)Yk(b?(h!>6+605*#_!hp<9t7AHAdu|k1f|{-J2=yMVZabQ z=NHwqQQaVW%oHCTw$(UA?jWU|OMfO~mC;2NbnCrkrlmzh!NH{zC1sP|xRRaGOmK3w zWayX7kuVN&7obug5H@RqqXC_LSVl+4jv~ zGD*Yxj^xl<4m>5|(VH-C8IDQm9UC6Sd92 zn1RKsqC4!8tnQ}q5eRjz#Hq$KN#S)`)ZHCKvU40eHID7^Pw!W2ZDO!J1|uIkqMJyOH?_VXUW zVeBA`yI~d;ww$48@v*_cs2cX*;Ba21@Lju9C4;)az@pO2qlV~Xz zj!NDN?N!c0XT?V$zbI@7@G&h?&8e1cG9 zEk$b+NOca-dZ81_Xp2*3Mp?~Os^I8=__XvhnqC1{yP`ejJ>F|oL5!UN(m^0Yb#=jB zh2NE1He<~smf*||x_Sor;Fc}8@-#m!nu=ZotXxJskOdmL4qEpe2BV@)>B12KZR;T_V;q2~3t;S2mocOSJ*sL5Fwv2dgM`sL>t+N+6=_8<(5>N#&?M zIa*+|8_neu@H@%)=pOGlELsi0I3Ccdb5o^{{AnTcvh{HVX z3|S+i<#(!SP3VnPn61hqXIcuy0?K&?`a#%X**;T#GNNzOM?<~iVt@M=}-CL+%! zU@Q;&GuZKl&nR#2Hqc2g?)$t=y-19uB3VvaKftsJ21Pb;JgxJ4}uJDENxg>Qr8|y%FIC?=G-H-kXuqd1vNe2V>8&X?9nW#KNz zfj~9ZzI5s%nf*q;&A+4tI_aJ;ol5%(%Tz$@e) z(Q4fe?N`)S<)OGl+w?2^b$F8?@9Fx>I(6wHR+ z|7PK5dok>Ogth)xKKpc55tk&VZxOyyQ_LfoYh-85Tiq)MQ(HFUD+Kos2TL=+NLRm7 z%x8X~@ypV_76S-I>bP849%a;U>+|`|c)i(QcLE)8C&wH@3`(!=2u;VhLQL@ua!CYS zy+$%K1!##iDnMSvCQM-ASV65T5Gi)*$R~`wIBoi-exP z?eP#!T;}WWITo=aE$QTl@SO=sLgSB*P{EexwQW(*OPlsJa^afF!77l{hPzZGOp^rp zz}P?zvG?X_V-3*Z;eXh0DkCSzB>%ut&_l6T?N%>Gde!{d1gvXl?2mK^G{pi!h)p^U z&e5CI^e*P6IXjg|wzzBxowh;rJ06AvJOL^x#}KdlWN-#lf1BZz;AwrXL7DYK=Tz{Z zG8a9PX=UUq0mU0EeZGkqb zrYyT8mxENp^o5%yQX^j`G_1OOqzVYvE(s>j<1SyR$@?FON z8-kCB4mFP%^;r%$MX8J$Jh|cHiF10a{ZfY2(7~S#f1NBS5`N(r?_UqaebG^2K9=x`BMi% zQ@LOZ6Sjk1eGS#TA)9=2Hd23zb6KmVfuk#T?(S^ZI%-|;m%ppI7U9RSZ{rK@aC z;G~b8HnExBi^U_xG@JryxaKoPv$+SKuuFtFeUNt4+hlyhYZ}TQ1dn&#HDVX8XzmoY z#zU8aqBf=n5#ZHC9XQR2$uR*gkL3n)(Z+}s;s#r{0tKd@sKC$9>Nnz%0j_H1EVE-d zIH;Kg&Vk*tp75ncKzloEh0+_nDsVEWqKcQrsI+BQu4QHelG?R1!kZb5Y?rFQiFbjj zg@n9_z*M1IwQ6PT)QL-DcnYW=%fhTfu@XN~SyqzPK3#=h$B@io$-YF;1KH|rfAS_;D5Sd zC_`sCi`ltZh1+1QSV-!v2oY4$IV`jZid99I;ByBxG3?bwoVLsNN^Y)7|B2P5F`Q^8 zelb$byG@W%u!|<1zUBpZME0MN2V*`WVe@?oTiOM7SeU-rfFey!WGMD5H#_v@4Hw7{Dvjy6v*KShm?Q) zpU?pR*Z)^&z;b^qe+C>nCDh85+4o2MtaUTTBtwbuLIt?G2~P!vB)SIbo$z&32441NRM|MH84f)z zs)vp(SfhpNn1SsVGhO-VZt6STB-F<|=6S!0iLr4YuBcave`M=F?MqyC54ELWAKh^w z)2OOgq&H`vZ-JDCgza2qSn(nn9l}B7?+lLGzX<@{Vh3Sa#1w%2fMKQq-8GI$JieW; zuk_OWc<~GxUZ5G$bfpsNL069bm@cL<|DwXi;kR^&28mu4h|hr>F)pTw4mLirqT+&u zY;O=5z>CRo4H9MkveN%hU%Fc7`638fy1pI^+5Ze#HaB^C1!{u)sibE7)2#C+UlY~e z74pxbyChWkjKkwCo?Fp}U!j`n@#@8F`m?PzKp+^(#+sAm>Q$OOqxs*MZ&b(v7f3w- z^dx1fz~Gb)&p{cZg3$|o#4jEV>D`7n^(!P}LuzNlCzXJ3ITw^J*BZ*u>y8J(q{{{Q zZKa*QC{xSfX8mW}kLT-i0GZIF@$mE`w6ujeIU#2@Y`vJjHw4ehD5O)~sa&up|H*kkYTuF$63ZoN@-_(x(v)*F|ws4OvnQ7KxslyW2 z@bAU@wsG%(Yp!dBQCp-)%L<`Dr2Px)U`~VI`93z^R{DZ=Fury5g^DwicsCpgJC|)b zP{7xsNp?8u|9R?ybtsnieUbgiZZ{v?&6fie!3;EvA4dz6fgjusBaS|7BaM!4t7OsouL#Udq>!DhO|9r+?r0?W8=xUOlEF41COc@K8<#ea zUJj<6;vzgEOo-Ob&X)GC+BSTEQl%#wPR18k_Np9w-4gfXU`lmz0-D=w2#B^j*f6|( zfd9V$x9nYg=|&zfLx!i-s>s-pX2Tmu_^1GN=@b%ZLk9RLiYPGnp=L&%-pT4Itd^T^A6=5BX1_sJ6DEmv^g<3R+!`gY zLF|)KB7_7HhPwTmb6^WBjP7MgM>$dK#(u_9YlCT^TgJb-dRw|hOQ)>CqGfY1+ylLkUP1~(S| z&GiR`fP2~`oPU!Y&>pa=wMSG1wBL6_x5+c-3R_lH{Tv>Tym?x4hI{Tf&EOL%`*>Ze zwXi8KY|-#V=mqwoYm4`d3!byY^JYmL1wBF$KQuDBOw$q8ug{5BEoPZx*vJ9JY1xuR zeF{{!5b3ER)^t(B10B!2$gJA?y8SX2G#(`ik=2cFH- zCgl_rs%|PGZbJdCgRr9X)I&;hS(jQ^eUR?`r{LfG!UrQ|Pn2UfzNmsE@Ax>_&%xQF zW4Dzh-L0acbXoJ)_x1J0%Gu$@ifY-MHSDjeW7_OH2zPU2gN(}})T_woC0a_XoYQT- zr%tZUm-sTbMwD!iKHTd!`m1mD`RPDiUfAv5^@4FY2UA8wzFsaL4JjvuR6SXBVC$L+ zr|wnrW?{V{@$8CB0WCj@%Z-v|=G^KDg)Uv?A;xd%;sIwSEb~{B*cE1BQ(l7ri>ZrA zX42CqClw+&y{d`8c>NFF3qe;iqVGEwUUO@Q+23_1YJvWN#u9Hq%Bx`7ZALw+RyGEh zS$cvq6)SCRL~eQ%6JTwDqm;FaXIS_nORkiZ#k61sCu^5l1ZU?@7ukgE9>cw|2xfKM zdRAY+>AC7YnnjC7hguK~{8;6>j4;%L)p=WQso53e8heC!y-mVQ_-~+hSx51omfGM4=aWPOw{_|XSNh~sR>6UYi zYA0;S=BHVrr6{pR@(Gqk@q2)Mh1jgl7A7Z*fjo$}v(N2a6BOS3{NBoxr;Kt@Y<26< zDNYiTOAHGs5HQ&PF87ar20PZl+JZ}56)YIBmGB}2W&L40q^N4!tfRv&#}Ph?&4|g=<=-t1Qq9TLyz@1226EfB zX2%_{B=^vK5qTsoMG7tAxdyuJ@(@11dPb9t1)2fs&YAnPY*%=P)kBl0T~V90G%2%Pdh5ms z&&1vaop5t}>Lm&&q3S4^HU5_f+pT33?Sro8C+QlO0MOTG@LCkL1d-fA%_x)bHNT{; zM6|uDLh}j(!~?Hz8T8=f!Bi%#fA^Bq*y{U*5TK$=MKn^bE$e#BG8Qun0a5s6Zyx(` zzohaQs|A5R=>8i+LzUY7$0`+!F-h#PJMVX7 z2md>=YbVDDw*UW)?DpdR&&V!^3Nz>bj_ej!TEAwbR79ueW;BN7);b2hN2#SJJ2FE7 zJn*1$XsTJIb@Q^k?*O8pDjB+Y*|5!3X{pat<2%@laJHat=3e(m`_TcP*&Ux>&-M?5 z5@A#AEj9mF8!)?x{QsTU*;7Jt4?@vx{a==7m;DhuE~F3?Uh(Nq56%V{O>lfB4(|v3 z=1)Clj_giuzAAt}%wq0TEqzh;l+U6C8-uBY0nId_^;sCNq*@c>GX#L|(X9B;th_c#`rkSsG5s+5P{1 zH<%ni99Sg@eP+sCZI*o0uvH1#O>@ljTc7Q{G#j!Cy1yN zR}YK_-m&W%lyV@#y2Da71r?~PDD(2#ZXAfblBb$OCJWC_{*{`=jzJh}DQ7q|wawIQ zj~IxB>awLj9Wldr1-S~vc&>)$=GBM3biRRZ6H+*N2ysn!n(?;I5XdWuQ#2*k(f)z_ z1Em(I4=~Aevr*_lp=`pN(l#+E8T5c#NNQgMWF4pPwYbxny#uN>9EAhPRqKMJwBI`M zT+4}nzKFzg^1z{4L*%oFhDi!;h8(ihBih!?JW8*HyjKdr%o{ zHsI0{d(QXr|1kB9!I?Z!zsbh-#HoeXr(Fzt*h+NHWQP_|>1ARr&-6d=_GBNG$D=uziy_kmek<4i5+xPe=4i z(Vr%)AMCkQTT&KxU3Mz(@EPzqm(`RsNXZUU3E^OzJ`!n5`WxYpje;bVH-S?jP=2gG zA`_hFrZj*v2cu^v0N(+FT)O~n6#dag*AcQa&(I997~c+;{15LtOZ#K4z>6>5|E#a? zu83g0@_7Q?tG5lcBpn=&UagFU!}FQ$1y{{JL(hO!}-tq z_%ZCthD!N92I`g{v_GoLlT_?MNVSbjmved>~jv zn|*y^4|L{fjec?-2b_hZ)dEB<@=Co&CGoWcRtlJy*}5 zdOLWY8YV2{;MtVIj@?K!RG%w?5+=e;gjp(n6yCSfv6)+DCzF{S{2G{--#Gnn!-R9#Is}YfFg))1@w~Axyo-`Fb zy1|;^XxK@V43e~t0hN1IhUby;Ngfycat4=X^7UWKICU9XbCUE6c>0C!a2bO=c0x;j z+Q(IM*a9V%0f~-&H{_}opf3*@T88l3 zUZgxsi?(B46(qa|u7nOkB|aeCZM6&WruvV1w7cg#}^60@2jboc^)(NGM@gZp|t z_GoHi7}I`pY*l9}Lxc87lGvs5Wd}voEuH#pT&1U>hXx+!BqUMeufEu>^0Ra8k&<

WgQ|a`vRpa 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

S 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

;E%#Ao2+`EH?F8{ayvVP0jl# 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 + +# This file is part of Open5GS. + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from docx import Document +import re, os, sys, string +import datetime +import getopt +import getpass + +version = "0.2.0" + +msg_list = {} +type_list = {} + +verbosity = 0 +filename = "" +outdir = './' +cachedir = './cache/' +currentdir = './' + +FAIL = '\033[91m' +INFO = '\033[93m' +ENDC = '\033[0m' + +def d_print(string): + if verbosity > 0: + sys.stdout.write(string) + +def d_info(string): + sys.stdout.write(INFO + string + ENDC + "\n") + +def d_error(string): + sys.stderr.write(FAIL + string + ENDC + "\n") + sys.exit(0) + +def write_file(f, string): + f.write(string) + d_print(string) + +def output_header_to_file(f): + now = datetime.datetime.now() + f.write("""/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +""") + f.write("/*******************************************************************************\n") + f.write(" * This file had been created by nas-message.py script v%s\n" % (version)) + f.write(" * Please do not modify this file but regenerate it via script.\n") + f.write(" * Created on: %s by %s\n * from %s\n" % (str(now), getpass.getuser(), filename)) + f.write(" ******************************************************************************/\n\n") + +def usage(): + print "Python generating NAS Message encoder/decoder v%s" % (version) + print "Usage: python nas-message.py [options]" + print "Available options:" + print "-d Enable script debug" + print "-f [file] Input file to parse" + print "-o [dir] Output files to given directory" + print "-c [dir] Cache files to given directory" + print "-h Print this help and return" + +def v_upper(v): + return re.sub('_TO_UE', '', re.sub('_FROM_UE', '', re.sub('\'', '_', re.sub('/', '_', re.sub('-', '_', re.sub(' ', '_', v)))).upper())) + +def v_lower(v): + return re.sub('\'', '_', re.sub('/', '_', re.sub('-', '_', re.sub(' ', '_', v)))).lower() + +def get_value(v): + return re.sub('5gs_', '', re.sub('5g_', '', re.sub('5gsm', 'gsm', re.sub('5gmm', 'gmm', re.sub('\'', '_', re.sub('/', '_', re.sub('-', '_', re.sub(' ', '_', v)))).lower())))) + +def get_cells(cells): + iei = cells[0].text.encode('ascii', 'ignore') + value = re.sub("\s*$", "", re.sub("\s*\n*\s*\([^\)]*\)*", "", re.sub("'s", "", cells[1].text))).encode('ascii', 'ignore') + type = re.sub("^NAS ", "", re.sub("'s", "", re.sub('\s*\n\s*[a-zA-Z0-9.]*', '', cells[2].text))).encode('ascii', 'ignore') + reference = re.sub('[a-zA-Z0-9\'\-\s]*\n\s*', '', cells[2].text).encode('ascii', 'ignore') + presence = cells[3].text.encode('ascii', 'ignore') + format = cells[4].text.encode('ascii', 'ignore') + length = cells[5].text.encode('ascii', 'ignore') + + return { "iei" : iei, "value" : value, "type" : type, "reference" : reference, "presence" : presence, "format" : format, "length" : length } + +def write_cells_to_file(name, cells): + write_file(f, name + ".append({ \"iei\" : \"" + cells["iei"] + \ + "\", \"value\" : \"" + cells["value"] + \ + "\", \"type\" : \"" + cells["type"] + \ + "\", \"reference\" : \"" + cells["reference"] + \ + "\", \"presence\" : \"" + cells["presence"] + \ + "\", \"format\" : \"" + cells["format"] + \ + "\", \"length\" : \"" + cells["length"] + "\"})\n") + +try: + opts, args = getopt.getopt(sys.argv[1:], "df:ho:c:", ["debug", "file", "help", "output", "cache"]) +except getopt.GetoptError as err: + # print help information and exit: + usage() + sys.exit(2) + +for o, a in opts: + if o in ("-d", "--debug"): + verbosity = 1 + if o in ("-f", "--file"): + filename = a + if o in ("-o", "--output"): + outdir = a + if outdir.rfind('/') != len(outdir): + outdir += '/' + if o in ("-c", "--cache"): + cache = a + if cachedir.rfind('/') != len(cachedir): + cachedir += '/' + if o in ("-h", "--help"): + usage() + sys.exit(2) + +# Message Type List + +msg_list["REGISTRATION REQUEST"] = { "type" : "65" } +msg_list["REGISTRATION ACCEPT"] = { "type" : "66" } +msg_list["REGISTRATION COMPLETE"] = { "type" : "67" } +msg_list["REGISTRATION REJECT"] = { "type" : "68" } +msg_list["DEREGISTRATION REQUEST FROM UE"] = { "type" : "69" } +msg_list["DEREGISTRATION ACCEPT FROM UE"] = { "type" : "70" } +msg_list["DEREGISTRATION REQUEST TO UE"] = { "type" : "71" } +msg_list["DEREGISTRATION ACCEPT TO UE"] = { "type" : "72" } +msg_list["SERVICE REQUEST"] = { "type" : "76" } +msg_list["SERVICE REJECT"] = { "type" : "77" } +msg_list["SERVICE ACCEPT"] = { "type" : "78" } +msg_list["CONFIGURATION UPDATE COMMAND"] = { "type" : "84" } +msg_list["CONFIGURATION UPDATE COMPLETE"] = { "type" : "85" } +msg_list["AUTHENTICATION REQUEST"] = { "type" : "86" } +msg_list["AUTHENTICATION RESPONSE"] = { "type" : "87" } +msg_list["AUTHENTICATION REJECT"] = { "type" : "88" } +msg_list["AUTHENTICATION FAILURE"] = { "type" : "89" } +msg_list["AUTHENTICATION RESULT"] = { "type" : "90" } +msg_list["IDENTITY REQUEST"] = { "type" : "91" } +msg_list["IDENTITY RESPONSE"] = { "type" : "92" } +msg_list["SECURITY MODE COMMAND"] = { "type" : "93" } +msg_list["SECURITY MODE COMPLETE"] = { "type" : "94" } +msg_list["SECURITY MODE REJECT"] = { "type" : "95" } +msg_list["5GMM STATUS"] = { "type" : "100" } +msg_list["NOTIFICATION"] = { "type" : "101" } +msg_list["NOTIFICATION RESPONSE"] = { "type" : "102" } +msg_list["UL NAS TRANSPORT"] = { "type" : "103" } +msg_list["DL NAS TRANSPORT"] = { "type" : "104" } + +msg_list["PDU SESSION ESTABLISHMENT REQUEST"] = { "type" : "193" } +msg_list["PDU SESSION ESTABLISHMENT ACCEPT"] = { "type" : "194" } +msg_list["PDU SESSION ESTABLISHMENT REJECT"] = { "type" : "195" } +msg_list["PDU SESSION AUTHENTICATION COMMAND"] = { "type" : "197" } +msg_list["PDU SESSION AUTHENTICATION COMPLETE"] = { "type" : "198" } +msg_list["PDU SESSION AUTHENTICATION RESULT"] = { "type" : "199" } +msg_list["PDU SESSION MODIFICATION REQUEST"] = { "type" : "201" } +msg_list["PDU SESSION MODIFICATION REJECT"] = { "type" : "202" } +msg_list["PDU SESSION MODIFICATION COMMAND"] = { "type" : "203" } +msg_list["PDU SESSION MODIFICATION COMPLETE"] = { "type" : "204" } +msg_list["PDU SESSION MODIFICATION COMMAND REJECT"] = { "type" : "205" } +msg_list["PDU SESSION RELEASE REQUEST"] = { "type" : "209" } +msg_list["PDU SESSION RELEASE REJECT"] = { "type" : "210" } +msg_list["PDU SESSION RELEASE COMMAND"] = { "type" : "211" } +msg_list["PDU SESSION RELEASE COMPLETE"] = { "type" : "212" } +msg_list["5GSM STATUS"] = { "type" : "214" } + +# Table number for Message List +msg_list["AUTHENTICATION REQUEST"]["table"] = 0 +msg_list["AUTHENTICATION RESPONSE"]["table"] = 1 +msg_list["AUTHENTICATION RESULT"]["table"] = 2 +msg_list["AUTHENTICATION FAILURE"]["table"] = 3 +msg_list["AUTHENTICATION REJECT"]["table"] = 4 +msg_list["REGISTRATION REQUEST"]["table"] = 5 +msg_list["REGISTRATION ACCEPT"]["table"] = 6 +msg_list["REGISTRATION COMPLETE"]["table"] = 7 +msg_list["REGISTRATION REJECT"]["table"] = 8 +msg_list["UL NAS TRANSPORT"]["table"] = 9 +msg_list["DL NAS TRANSPORT"]["table"] = 10 +msg_list["DEREGISTRATION REQUEST FROM UE"]["table"] = 11 +msg_list["DEREGISTRATION ACCEPT FROM UE"]["table"] = 12 +msg_list["DEREGISTRATION REQUEST TO UE"]["table"] = 13 +msg_list["DEREGISTRATION ACCEPT TO UE"]["table"] = 14 +msg_list["SERVICE REQUEST"]["table"] = 15 +msg_list["SERVICE ACCEPT"]["table"] = 16 +msg_list["SERVICE REJECT"]["table"] = 17 +msg_list["CONFIGURATION UPDATE COMMAND"]["table"] = 18 +msg_list["CONFIGURATION UPDATE COMPLETE"]["table"] = 29 +msg_list["IDENTITY REQUEST"]["table"] = 20 +msg_list["IDENTITY RESPONSE"]["table"] = 21 +msg_list["NOTIFICATION"]["table"] = 22 +msg_list["NOTIFICATION RESPONSE"]["table"] = 23 +msg_list["SECURITY MODE COMMAND"]["table"] = 24 +msg_list["SECURITY MODE COMPLETE"]["table"] = 25 +msg_list["SECURITY MODE REJECT"]["table"] = 26 +msg_list["5GMM STATUS"]["table"] = 28 + +msg_list["PDU SESSION ESTABLISHMENT REQUEST"]["table"] = 29 +msg_list["PDU SESSION ESTABLISHMENT ACCEPT"]["table"] = 30 +msg_list["PDU SESSION ESTABLISHMENT REJECT"]["table"] = 31 +msg_list["PDU SESSION AUTHENTICATION COMMAND"]["table"] = 32 +msg_list["PDU SESSION AUTHENTICATION COMPLETE"]["table"] = 33 +msg_list["PDU SESSION AUTHENTICATION RESULT"]["table"] = 34 +msg_list["PDU SESSION MODIFICATION REQUEST"]["table"] = 35 +msg_list["PDU SESSION MODIFICATION REJECT"]["table"] = 36 +msg_list["PDU SESSION MODIFICATION COMMAND"]["table"] = 37 +msg_list["PDU SESSION MODIFICATION COMPLETE"]["table"] = 38 +msg_list["PDU SESSION MODIFICATION COMMAND REJECT"]["table"] = 39 +msg_list["PDU SESSION RELEASE REQUEST"]["table"] = 40 +msg_list["PDU SESSION RELEASE REJECT"]["table"] = 41 +msg_list["PDU SESSION RELEASE COMMAND"]["table"] = 42 +msg_list["PDU SESSION RELEASE COMPLETE"]["table"] = 43 +msg_list["5GSM STATUS"]["table"] = 44 + +for key in msg_list.keys(): + if "table" not in msg_list[key].keys(): + continue; + + d_info("[" + key + "]") + cachefile = cachedir + "nas-msg-" + msg_list[key]["type"] + ".py" + if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK): + execfile(cachefile) + print "Read from " + cachefile + else: + document = Document(filename) + f = open(cachefile, 'w') + + ies = [] + write_file(f, "ies = []\n") + table = document.tables[msg_list[key]["table"]] + + start_row = 0 + for start_row, row in enumerate(table.rows): + cells = get_cells(row.cells); + if cells["type"].find('Message type') != -1: + break + if cells["type"].find('KSI and sequence number') != -1: + start_row -= 1 + break + + assert start_row <= 4, "Can't find message type" + + half_length = True; + for row in table.rows[start_row+1:]: + cells = get_cells(row.cells) + if cells is None: + continue + + if cells["length"] == "1/2": + if half_length is True: + half_length = False; + else: + half_length = True; + continue; + + ies.append(cells) + write_cells_to_file("ies", cells) + + msg_list[key]["ies"] = ies + write_file(f, "msg_list[key][\"ies\"] = ies\n") + + f.close() + + +tmp = [(k, v["type"]) for k, v in msg_list.items()] +sorted_msg_list = sorted(tmp, key=lambda tup: float(tup[1])) + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + + for ie in msg_list[k]["ies"]: + key = ie["type"] + if key in type_list.keys() and (type_list[key]["presence"] != ie["presence"] or type_list[key]["format"] != ie["format"] or type_list[key]["length"] != ie["length"]): + d_print("KEY type different : %s\n" % key) + d_print("%s.%s %s %s %s\n" % (v_lower(type_list[key]["message"]), type_list[key]["value"], type_list[key]["presence"], type_list[key]["format"], type_list[key]["length"])) + d_print("%s.%s %s %s %s\n\n" % (v_lower(k), ie["value"], ie["presence"], ie["format"], ie["length"])) + continue + type_list[key] = { "reference" : ie["reference"], "presence" : ie["presence"], "format" : ie["format"], "length" : ie["length"], "message" : k, "value" : ie["value"] } + +d_info("[Type List]") +typefile = currentdir + "type-list.py" +if os.path.isfile(typefile) and os.access(typefile, os.R_OK): + execfile(typefile) + print "Read from " + typefile + +tmp = [(k, v["reference"]) for k, v in type_list.items()] +sorted_type_list = sorted(tmp, key=lambda tup: tup[1]) + +f = open(outdir + 'ies.h', 'w') +output_header_to_file(f) +f.write("""#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_5GS_IES_H +#define OGS_NAS_5GS_IES_H + +#ifdef __cplusplus +extern "C" { +#endif + +int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type); + +""") + +for (k, v) in sorted_type_list: + f.write("int ogs_nas_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf);\n" % (v_lower(k), v_lower(k), get_value(k))) +f.write("\n") + +for (k, v) in sorted_type_list: + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_%s_t *%s);\n" % (v_lower(k), v_lower(k), get_value(k))) +f.write("\n") + + +f.write("""#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_IES_H */ + +""") +f.close() + +f = open(outdir + 'ies.c', 'w') +output_header_to_file(f) +f.write("""#include "ogs-nas-5gs.h" + +int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) +{ + uint16_t size = sizeof(uint8_t); + + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &type, size); + + return size; +} +""") + +for (k, v) in sorted_type_list: +# d_print("%s = %s\n" % (k, type_list[k])) + f.write("/* %s %s\n" % (type_list[k]["reference"], k)) + f.write(" * %s %s %s */\n" % (type_list[k]["presence"], type_list[k]["format"], type_list[k]["length"])) + if (type_list[k]["format"] == "TV" or type_list[k]["format"] == "T") and type_list[k]["length"] == "1": + f.write("int ogs_nas_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(" memcpy(%s, pkbuf->data - 1, 1);\n\n" % get_value(k)) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - 1, 1);\n\n"); + f.write(" return 0;\n") + f.write("}\n\n") + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_%s_t *%s)\n" % (v_lower(k), v_lower(k), get_value(k))) + f.write("{\n") + f.write(" uint16_t size = sizeof(ogs_nas_%s_t);\n\n" % v_lower(k)) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(pkbuf->data - size, %s, size);\n\n" % get_value(k)) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return size;\n") + f.write("}\n\n") + elif type_list[k]["format"] == "TV" or type_list[k]["format"] == "V": + f.write("int ogs_nas_decode_%s(ogs_nas_%s_t *%s, ogs_pkbuf_t *pkbuf)\n" % (v_lower(k), v_lower(k), get_value(k))) + f.write("{\n") + if type_list[k]["length"] == "4": + f.write(" uint16_t size = 3;\n\n") + else: + f.write(" uint16_t size = sizeof(ogs_nas_%s_t);\n\n" % v_lower(k)) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(%s, pkbuf->data - size, size);\n\n" % get_value(k)) + if "decode" in type_list[k]: + f.write("%s" % type_list[k]["decode"]) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return size;\n") + f.write("}\n\n") + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_%s_t *%s)\n" % (v_lower(k), v_lower(k), get_value(k))) + f.write("{\n") + if type_list[k]["length"] == "4": + f.write(" uint16_t size = 3;\n") + else: + f.write(" uint16_t size = sizeof(ogs_nas_%s_t);\n" % v_lower(k)) + f.write(" ogs_nas_%s_t target;\n\n" % v_lower(k)) + f.write(" memcpy(&target, %s, size);\n" % get_value(k)) + if "encode" in type_list[k]: + f.write("%s" % type_list[k]["encode"]) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(pkbuf->data - size, &target, size);\n\n") + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return size;\n") + f.write("}\n\n") + elif (type_list[k]["format"] == "LV-E" or type_list[k]["format"] == "TLV-E") and type_list[k]["value"] != "5GS mobile identity": + f.write("int ogs_nas_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(" uint16_t 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(" %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(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" %s->buffer = pkbuf->data - size + sizeof(%s->length);\n\n" % (get_value(k), get_value(k))) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, (void*)%s->buffer, %s->length);\n\n" % (get_value(k), get_value(k))); + f.write(" return size;\n") + f.write("}\n\n") + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_%s_t *%s)\n" % (v_lower(k), v_lower(k), get_value(k))) + f.write("{\n") + f.write(" uint16_t size = 0;\n") + f.write(" uint16_t target;\n\n") + f.write(" ogs_assert(%s);\n" % get_value(k)) + f.write(" ogs_assert(%s->buffer);\n\n" % get_value(k)) + f.write(" size = sizeof(%s->length);\n" % get_value(k)) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" target = htobe16(%s->length);\n" % get_value(k)) + f.write(" memcpy(pkbuf->data - size, &target, size);\n\n") + f.write(" size = %s->length;\n" % get_value(k)) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(pkbuf->data - size, %s->buffer, size);\n\n" % get_value(k)) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return %s->length + sizeof(%s->length);\n" % (get_value(k), get_value(k))) + f.write("}\n\n"); + else: + f.write("int ogs_nas_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(" uint16_t 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(" %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(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(%s, pkbuf->data - size, size);\n\n" % get_value(k)) + if "decode" in type_list[k]: + f.write("%s" % type_list[k]["decode"]) + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return size;\n") + f.write("}\n\n") + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_%s_t *%s)\n" % (v_lower(k), v_lower(k), get_value(k))) + f.write("{\n") + f.write(" uint16_t size = %s->length + sizeof(%s->length);\n" % (get_value(k), get_value(k))) + f.write(" ogs_nas_%s_t target;\n\n" % v_lower(k)) + f.write(" memcpy(&target, %s, sizeof(ogs_nas_%s_t));\n" % (get_value(k), v_lower(k))) + if "encode" in type_list[k]: + f.write("%s" % type_list[k]["encode"]) + f.write(" ogs_assert(ogs_pkbuf_pull(pkbuf, size));\n") + f.write(" memcpy(pkbuf->data - size, &target, size);\n\n") + f.write(" ogs_trace(\" %s - \");\n" % v_upper(k)) + f.write(" ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);\n\n"); + f.write(" return size;\n") + f.write("}\n\n"); +f.close() + +f = open(outdir + 'message.h', 'w') +output_header_to_file(f) +f.write("""#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_5GS_MESSAGE_H +#define OGS_NAS_5GS_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ +#define OGS_NAS_HEADROOM 16 + +#define OGS_NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE 0 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED 1 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED 2 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT 3 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHTERD_WITH_NEW_INTEGRITY_CONTEXT 4 +#define OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_PARTICALLY_CIPHTERD 5 + +#define OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_ESM 0x2e +#define OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_EMM 0x7e + +#define OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED 0 +#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0 + +typedef struct ogs_nas_5gmm_header_s { + uint8_t extended_protocol_discriminator; + uint8_t security_header_type; + uint8_t message_type; +} __attribute__ ((packed)) ogs_nas_5gmm_header_t; + +typedef struct ogs_nas_5gsm_header_s { + uint8_t extended_protocol_discriminator; + uint8_t pdu_session_identity; + uint8_t procedure_transaction_identity; + uint8_t message_type; +} __attribute__ ((packed)) ogs_nas_5gsm_header_t; + +typedef struct ogs_nas_security_header_s { + uint8_t extended_protocol_discriminator; + uint8_t security_header_type; + uint32_t message_authentication_code; + uint8_t sequence_number; +} __attribute__ ((packed)) ogs_nas_security_header_t; + +""") + +for (k, v) in sorted_msg_list: + if k.find("TO UE") == -1: + f.write("#define OGS_NAS_" + v_upper(k) + " " + v.split('.')[0] + "\n") +f.write("\n") + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if len(msg_list[k]["ies"]) == 0: + continue; + + f.write("\n/*******************************************************\n") + f.write(" * %s\n" % k) + f.write(" ******************************************************/") + + for i, ie in enumerate([ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]): + f.write("\n#define OGS_NAS_%s_%s_PRESENT ((uint64_t)1<<%d)" % (v_upper(k), v_upper(ie["value"]), i)) + + for i, ie in enumerate([ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]): + f.write("\n#define OGS_NAS_%s_%s_TYPE 0x%s" % (v_upper(k), v_upper(ie["value"]), re.sub('-', '0', ie["iei"]))) + + f.write("\n\ntypedef struct ogs_nas_%s_s {\n" % v_lower(k)) + + mandatory_fields = False; + optional_fields = False; + for ie in msg_list[k]["ies"]: + if ie["presence"] == "M" and mandatory_fields is False: + f.write(" /* Mandatory fields */\n") + mandatory_fields = True; + + if ie["presence"] == "O" and optional_fields is False: + f.write("\n /* Optional fields */\n") + f.write(" uint64_t presencemask;\n"); + optional_fields = True; + + f.write(" ogs_nas_" + v_lower(ie["type"]) + "_t " + \ + get_value(ie["value"]) + ";\n") + + f.write("} ogs_nas_%s_t;\n\n" % v_lower(k)) + +f.write("\n") + +f.write("""typedef struct ogs_nas_5gmm_message_s { + ogs_nas_5gmm_header_t h; + union { +""") +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if len(msg_list[k]["ies"]) == 0: + continue; + if float(msg_list[k]["type"]) < 192: + f.write(" ogs_nas_%s_t %s;\n" % (v_lower(k), get_value(k))) +f.write(""" }; +} ogs_nas_5gmm_message_t; + +typedef struct ogs_nas_5gsm_message_s { + ogs_nas_5gsm_header_t h; + union { +""") +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if len(msg_list[k]["ies"]) == 0: + continue; + if float(msg_list[k]["type"]) >= 192: + f.write(" ogs_nas_%s_t %s;\n" % (v_lower(k), get_value(k))) + +f.write(""" }; +} ogs_nas_5gsm_message_t; + +typedef struct ogs_nas_message_s { + ogs_nas_security_header_t h; + union { + ogs_nas_5gmm_message_t gmm; + ogs_nas_5gsm_message_t gsm; + }; +} ogs_nas_message_t; + +ogs_pkbuf_t *ogs_nas_5gmm_encode(ogs_nas_message_t *message); +ogs_pkbuf_t *ogs_nas_5gsm_encode(ogs_nas_message_t *message); +int ogs_nas_5gmm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_5gsm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_MESSAGE_H */ +""") + +f.close() + + + +f = open(outdir + 'decoder.c', 'w') +output_header_to_file(f) +f.write("""#include "ogs-nas-5gs.h" + +""") + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue + if len(msg_list[k]["ies"]) == 0: + continue + f.write("int ogs_nas_decode_%s(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf);\n" % v_lower(k)) + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue + if len(msg_list[k]["ies"]) == 0: + continue + + f.write("int ogs_nas_decode_%s(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf)\n{\n" % v_lower(k)) + if float(msg_list[k]["type"]) < 192: + f.write(" ogs_nas_%s_t *%s = &message->gmm.%s;\n" % (v_lower(k), get_value(k), get_value(k))) + else: + f.write(" ogs_nas_%s_t *%s = &message->gsm.%s;\n" % (v_lower(k), get_value(k), get_value(k))) + f.write(" int decoded = 0;\n") + f.write(" int size = 0;\n\n") + f.write(" ogs_trace(\"[NAS] Decode %s\\n\");\n\n" % v_upper(k)) + + for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "M"]: + f.write(" size = ogs_nas_decode_%s(&%s->%s, pkbuf);\n" % (v_lower(ie["type"]), get_value(k), get_value(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" decoded += size;\n\n") + + optional_fields = False; + for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: + if optional_fields is False: + f.write(""" while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch(type) { +""") + optional_fields = True; + + f.write(" case OGS_NAS_%s_%s_TYPE:\n" % (v_upper(k), v_upper(ie["value"]))) + f.write(" size = ogs_nas_decode_%s(&%s->%s, pkbuf);\n" % (v_lower(ie["type"]), get_value(k), get_value(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" %s->presencemask |= OGS_NAS_%s_%s_PRESENT;\n" % (get_value(k), v_upper(k), v_upper(ie["value"]))) + f.write(" decoded += size;\n") + f.write(" break;\n") + + if [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: + f.write(""" default: + ogs_warn("Unknown type(0x%x) or not implemented\\n", type); + break; + } + } + +""") + f.write(""" return decoded; +} + +""") + +f.write("""int ogs_nas_5gmm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_5gmm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->gmm.h, pkbuf->data - size, size); + decoded += size; + + switch(message->gmm.h.message_type) { +""") +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if float(msg_list[k]["type"]) < 192 and k.find("TO UE") == -1: + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + if len(msg_list[k]["ies"]) != 0: + f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" decoded += size;\n") + f.write(" break;\n") + +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gmm.h.message_type); + break; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} +""") + +f.write("""int ogs_nas_5gsm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_5gsm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->gsm.h, pkbuf->data - size, size); + decoded += size; + + switch(message->gsm.h.message_type) { +""") +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if float(msg_list[k]["type"]) >= 192: + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + if len(msg_list[k]["ies"]) != 0: + f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" decoded += size;\n") + f.write(" break;\n") + +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gsm.h.message_type); + break; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} + +""") + +f.close() + +f = open(outdir + 'encoder.c', 'w') +output_header_to_file(f) +f.write("""#include "ogs-nas-5gs.h" + +""") + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if len(msg_list[k]["ies"]) == 0: + continue + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message);\n" % v_lower(k)) + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if len(msg_list[k]["ies"]) == 0: + continue + + f.write("int ogs_nas_encode_%s(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message)\n{\n" % v_lower(k)) + if float(msg_list[k]["type"]) < 192: + f.write(" ogs_nas_%s_t *%s = &message->gmm.%s;\n" % (v_lower(k), get_value(k), get_value(k))) + else: + f.write(" ogs_nas_%s_t *%s = &message->gsm.%s;\n" % (v_lower(k), get_value(k), get_value(k))) + f.write(" int encoded = 0;\n") + f.write(" int size = 0;\n\n") + f.write(" ogs_trace(\"[NAS] Encode %s\");\n\n" % v_upper(k)) + + for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "M"]: + f.write(" size = ogs_nas_encode_%s(pkbuf, &%s->%s);\n" % (v_lower(ie["type"]), get_value(k), get_value(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n\n") + + for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: + f.write(" if (%s->presencemask & OGS_NAS_%s_%s_PRESENT) {\n" % (get_value(k), v_upper(k), v_upper(ie["value"]))) + if ie["length"] == "1" and ie["format"] == "TV": + f.write(" %s->%s.type = (OGS_NAS_%s_%s_TYPE >> 4);\n\n" % (get_value(k), get_value(ie["value"]), v_upper(k), v_upper(ie["value"]))) + elif ie["length"] == "1" and ie["format"] == "T": + f.write(" %s->%s.type = OGS_NAS_%s_%s_TYPE;\n\n" % (get_value(k), get_value(ie["value"]), v_upper(k), v_upper(ie["value"]))) + else: + f.write(" size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_%s_%s_TYPE);\n" % (v_upper(k), v_upper(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n\n") + f.write(" size = ogs_nas_encode_%s(pkbuf, &%s->%s);\n" % (v_lower(ie["type"]), get_value(k), get_value(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n") + f.write(" }\n\n") + + f.write(""" return encoded; +} + +""") + + +f.write("""ogs_pkbuf_t *ogs_nas_5gmm_encode(ogs_nas_message_t *message) +{ + ogs_pkbuf_t *pkbuf = NULL; + int size = 0; + int encoded = 0; + + ogs_assert(message); + + /* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ + pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); + ogs_assert(pkbuf); + ogs_pkbuf_reserve(pkbuf, OGS_NAS_HEADROOM); + ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-OGS_NAS_HEADROOM); + + size = sizeof(ogs_nas_5gmm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + + memcpy(pkbuf->data - size, &message->gmm.h, size); + encoded += size; + + switch(message->gmm.h.message_type) { +""") + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if float(msg_list[k]["type"]) < 192 and k.find("FROM UE") == -1: + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + if len(msg_list[k]["ies"]) != 0: + f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n") + f.write(" break;\n") + +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gmm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); + + pkbuf->len = encoded; + + return pkbuf; +} + +""") + +f.write("""ogs_pkbuf_t *ogs_nas_5gsm_encode(ogs_nas_message_t *message) +{ + ogs_pkbuf_t *pkbuf = NULL; + int size = 0; + int encoded = 0; + + ogs_assert(message); + + /* The Packet Buffer(ogs_pkbuf_t) for NAS message MUST make a HEADROOM. + * When calculating AES_CMAC, we need to use the headroom of the packet. */ + pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN); + ogs_assert(pkbuf); + ogs_pkbuf_reserve(pkbuf, OGS_NAS_HEADROOM); + ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN-OGS_NAS_HEADROOM); + + size = sizeof(ogs_nas_5gsm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(pkbuf->data - size, &message->gsm.h, size); + encoded += size; + + switch(message->gsm.h.message_type) { +""") + +for (k, v) in sorted_msg_list: + if "ies" not in msg_list[k]: + continue; + if float(msg_list[k]["type"]) >= 192: + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + if len(msg_list[k]["ies"]) != 0: + f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n") + f.write(" break;\n") + +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->gsm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); + pkbuf->len = encoded; + + return pkbuf; +} + +ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message) +{ + ogs_assert(message); + + ogs_assert(message->gmm.h.extended_protocol_discriminator == + message->gsm.h.extended_protocol_discriminator); + + if (message->gmm.h.extended_protocol_discriminator == + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_EMM) + return ogs_nas_5gmm_encode(message); + else if (message->gmm.h.extended_protocol_discriminator == + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_ESM) + return ogs_nas_5gsm_encode(message); + + return NULL; +} +""") + +f.close() + diff --git a/lib/nas/5gs/support/type-list.py b/lib/nas/5gs/support/type-list.py new file mode 100644 index 000000000..94a68d19a --- /dev/null +++ b/lib/nas/5gs/support/type-list.py @@ -0,0 +1,53 @@ + +# Copyright (C) 2019 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 . + +type_list["5GS tracking area identity"]["decode"] = \ +" tracking_area_identity->tac = be16toh(tracking_area_identity->tac);\n\n" +type_list["5GS tracking area identity"]["encode"] = \ +" target.tac = htobe16(tracking_area_identity->tac);\n\n" + +type_list["5GS mobile identity"]["decode"] = \ +" if (mobile_identity->guti.type == OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) {\n" \ +" mobile_identity->guti.m_tmsi = be32toh(mobile_identity->guti.m_tmsi);\n" \ +" } else if (mobile_identity->s_tmsi.type == OGS_NAS_5GS_MOBILE_IDENTITY_S_TMSI) {\n" \ +" mobile_identity->s_tmsi.m_tmsi = be32toh(mobile_identity->s_tmsi.m_tmsi);\n" \ +" }\n\n" +type_list["5GS mobile identity"]["encode"] = \ +" if (mobile_identity->guti.type == OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) {\n" \ +" target.guti.m_tmsi = htobe32(mobile_identity->guti.m_tmsi);\n" \ +" target.guti._0xf = 0xf;\n" \ +" } else if (mobile_identity->s_tmsi.type == OGS_NAS_5GS_MOBILE_IDENTITY_S_TMSI) {\n" \ +" target.s_tmsi.m_tmsi = htobe32(mobile_identity->s_tmsi.m_tmsi);\n" \ +" target.s_tmsi._0xf = 0xf;\n" \ +" }\n\n" + +type_list["Header compression configuration"]["decode"] = \ +" header_compression_configuration->max_cid = be16toh(header_compression_configuration->max_cid);\n\n" +type_list["Header compression configuration"]["encode"] = \ +" target.max_cid = htobe16(header_compression_configuration->max_cid);\n\n" + +type_list["DNN"]["decode"] = \ +" {\n" \ +" char data_network_name[OGS_MAX_DNN_LEN];\n" \ +" dnn->length = ogs_fqdn_parse(data_network_name, dnn->value, dnn->length);\n" \ +" ogs_cpystrn(dnn->value, data_network_name, ogs_min(dnn->length, OGS_MAX_DNN_LEN) + 1);\n" \ +" }\n\n" + +type_list["DNN"]["encode"] = \ +" target.length = ogs_fqdn_build(target.value, dnn->value, dnn->length);\n" \ +" size = target.length + sizeof(target.length);\n\n" diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h new file mode 100644 index 000000000..eb3e1efa8 --- /dev/null +++ b/lib/nas/5gs/types.h @@ -0,0 +1,959 @@ +/* + * Copyright (C) 2019 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_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_5GS_TYPES_H +#define OGS_NAS_5GS_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* 9.11.2.1A DNN + * O TLV 3-102 */ +typedef struct ogs_nas_dnn_s { + uint8_t length; + char value[OGS_MAX_DNN_LEN]; +} ogs_nas_dnn_t; + +/* 9.11.2.2 EAP message + * O TLV-E 7-1503 */ +typedef struct ogs_nas_eap_message_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_eap_message_t; + +/* 9.11.2.8.1 S-NSSAI + * O TLV 3-10 */ +#define OGS_NAS_S_NSSAI_SST_LEN 1 +#define OGS_NAS_S_NSSAI_SST_AND_MAPPED_HPLMN_SST_LEN 2 +#define OGS_NAS_S_NSSAI_SST_AND_SD 4 +#define OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_LEN 5 +#define OGS_NAS_MAX_S_NSSAI_LEN 8 +typedef struct ogs_nas_s_nssai_s { + uint8_t length; + uint32_t sst_sd; + uint32_t mapped_sst_sd; +} __attribute__ ((packed)) ogs_nas_s_nssai_t; + +/* 9.11.3.1 5GMM capability + * O TLV 3-15 */ +typedef struct ogs_nas_5gmm_capability_s { + uint8_t length; +ED4(uint8_t spare:5;, + uint8_t lpp:1;, + uint8_t ho:1;, + uint8_t s1:1;) +} __attribute__ ((packed)) ogs_nas_5gmm_capability_t; + +/* 9.11.3.2 5GMM cause + * M V 1 */ +#define OGS_NAS_GMM_ILLEGAL_UE 3 +#define OGS_NAS_GMM_PEI_NOT_ACCEPTED 5 +#define OGS_NAS_GMM_ILLEGAL_ME 6 +#define OGS_NAS_GMM_5GS_SERVICES_NOT_ALLOWED 7 +#define OGS_NAS_GMM_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK 9 +#define OGS_NAS_GMM_IMPLICITLY_DE_REGISTERED 10 +#define OGS_NAS_GMM_PLMN_NOT_ALLOWED 11 +#define OGS_NAS_GMM_TRACKING_AREA_NOT_ALLOWED 12 +#define OGS_NAS_GMM_ROAMING_NOT_ALLOWED_IN_THIS_TRACKING_AREA 13 +#define OGS_NAS_GMM_NO_SUITABLE_CELLS_IN_TRACKING_AREA 15 +#define OGS_NAS_GMM_MAC_FAILURE 20 +#define OGS_NAS_GMM_SYNCH_FAILURE 21 +#define OGS_NAS_GMM_CONGESTION 22 +#define OGS_NAS_GMM_UE_SECURITY_CAPABILITIES_MISMATCH 23 +#define OGS_NAS_GMM_SECURITY_MODE_REJECTED_UNSPECIFIED 24 +#define OGS_NAS_GMM_NON_5G_AUTHENTICATION_UNACCEPTABLE 26 +#define OGS_NAS_GMM_N1_MODE_NOT_ALLOWED 27 +#define OGS_NAS_GMM_RESTRICTED_SERVICE_AREA 28 +#define OGS_NAS_GMM_LADN_NOT_AVAILABLE 43 +#define OGS_NAS_GMM_MAXIMUM_NUMBER_OF_PDU_SESSIONS_REACHED 65 +#define OGS_NAS_GMM_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN 67 +#define OGS_NAS_GMM_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE 69 +#define OGS_NAS_GMM_NGKSI_ALREADY_IN_USE 71 +#define OGS_NAS_GMM_NON_3GPP_ACCESS_TO_5GCN_NOT_ALLOWED 72 +#define OGS_NAS_GMM_SERVING_NETWORK_NOT_AUTHORIZED 73 +#define OGS_NAS_GMM_PAYLOAD_WAS_NOT_FORWARDED 90 +#define OGS_NAS_GMM_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE 91 +#define OGS_NAS_GMM_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION 92 +#define OGS_NAS_GMM_SEMANTICALLY_INCORRECT_MESSAGE 95 +#define OGS_NAS_GMM_INVALID_MANDATORY_INFORMATION 96 +#define OGS_NAS_GMM_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED 97 +#define OGS_NAS_GMM_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 98 +#define OGS_NAS_GMM_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED 99 +#define OGS_NAS_GMM_CONDITIONAL_IE_ERROR 100 +#define OGS_NAS_GMM_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 101 +#define OGS_NAS_GMM_PROTOCOL_ERROR_UNSPECIFIED 111 +typedef uint8_t ogs_nas_5gmm_cause_t; + +/* 9.11.3.2A 5GS DRX parameters + * O TLV 3 */ +#define OGS_NAS_DRX_CYCLE_PARAMETER_T_32 1 +#define OGS_NAS_DRX_CYCLE_PARAMETER_T_64 2 +#define OGS_NAS_DRX_CYCLE_PARAMETER_T_128 3 +#define OGS_NAS_DRX_CYCLE_PARAMETER_T_256 4 +typedef struct ogs_nas_5gs_drx_parameters_s { + uint8_t length; +ED2(uint8_t spare:4;, + uint8_t value:4;) +} __attribute__ ((packed)) ogs_nas_5gs_drx_parameters_t; + +/* 9.11.3.3 5GS identity type + * M V 1/2 */ +#define OGS_NAS_5GS_MOBILE_IDENTITY_IS_NOT_AVAILABLE 0 +#define OGS_NAS_5GS_MOBILE_IDENTITY_SUCI 1 +#define OGS_NAS_5GS_MOBILE_IDENTITY_GUTI 2 +#define OGS_NAS_5GS_MOBILE_IDENTITY_IMEI 3 +#define OGS_NAS_5GS_MOBILE_IDENTITY_S_TMSI 4 +#define OGS_NAS_5GS_MOBILE_IDENTITY_IMEISV 5 +typedef struct ogs_nas_5gs_identity_type_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_5gs_identity_type_t; + +/* 9.11.3.4 5GS mobile identity + * M LV-E 6-n */ +#define OGS_NAS_GET_AMF_SET_ID(_iDentity) \ + ((_iDentity)->amf_set_id2 + ((_iDentity)->amf_set_id1 << 2)) +#define OGS_NAS_SET_AMF_SET_ID(_iDentity, _aMFSetId) \ + do { \ + ogs_assert((_iDentity)); \ + (_iDentity)->amf_set_id1 = (_aMFSetId >> 2) & 0x000f; \ + (_iDentity)->amf_set_id2 = _aMFSetId & 0x0003; \ + } while(0) +typedef struct ogs_nas_5gs_mobile_identity_guti_s { +ED3(uint8_t _0xf:4;, + uint8_t spare:1;, + uint8_t type:3;) + ogs_nas_plmn_id_t nas_plmn_id; + uint16_t amf_region_id; + uint8_t amf_set_id1; +ED2(uint8_t amf_set_id2:2;, + uint8_t amf_pointer:6;) + uint32_t m_tmsi; +} __attribute__ ((packed)) ogs_nas_5gs_mobile_identity_guti_t; +typedef struct ogs_nas_5gs_mobile_identity_s_tmsi_s { +ED3(uint8_t _0xf:4;, + uint8_t spare:1;, + uint8_t type:3;) + uint16_t amf_region_id; + uint8_t amf_set_id1; +ED2(uint8_t amf_set_id2:2;, + uint8_t amf_pointer:6;) + uint32_t m_tmsi; +} __attribute__ ((packed)) ogs_nas_5gs_mobile_identity_s_tmsi_t; +typedef struct ogs_nas_5gs_mobile_identity_s { + uint16_t length; + union { + ogs_nas_mobile_identity_imsi_t imsi; + ogs_nas_5gs_mobile_identity_guti_t guti; + ogs_nas_5gs_mobile_identity_s_tmsi_t s_tmsi; + ogs_nas_mobile_identity_imei_t imei; + ogs_nas_mobile_identity_imeisv_t imeisv; + }; +} ogs_nas_5gs_mobile_identity_t; + +/* 9.11.3.5 5GS network feature support + * M LV 2 */ +typedef struct ogs_nas_5gs_network_feature_support_s { + uint8_t length; +ED6(uint8_t mpsi:1;, + uint8_t iwk_n26:1;, + uint8_t emf:2;, + uint8_t msc:2;, + uint8_t ims_vops_n3gpp:1;, + uint8_t ims_vops_3gpp:1;) +ED3(uint8_t spare:6;, + uint8_t mcsi:1;, + uint8_t emcn :1;) +} ogs_nas_5gs_network_feature_support_t; + +/* 9.11.3.6 5GS registration result + * O TLV 3-5 */ +#define OGS_NAS_5GS_REGISTRATION_TYPE_3GPP_ACCESS 0 +#define OGS_NAS_5GS_REGISTRATION_TYPE_NON_3GPP_ACCESS 1 +#define OGS_NAS_5GS_REGISTRATION_TYPE_3GPP_AND_NON_3GPP_ACCESS 2 +typedef struct ogs_nas_5gs_registration_result_s { + uint8_t length; +ED3(uint8_t spare:4;, + uint8_t sms_allowed:1;, + uint8_t value:3;) +} ogs_nas_5gs_registration_result_t; + +/* 9.11.3.7 5GS registration type + * M V 1/2 */ +#define OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL 1 +#define OGS_NAS_5GS_REGISTRATION_TYPE_MOBILITY_UPDATING 2 +#define OGS_NAS_5GS_REGISTRATION_TYPE_PERIODIC_UPDATING 3 +#define OGS_NAS_5GS_REGISTRATION_TYPE_EMERGENCY 4 +typedef struct ogs_nas_5gs_registration_type_s { +ED3(uint8_t type:4;, + uint8_t follow_on_request:1;, + uint8_t value:3;) +} ogs_nas_5gs_registration_type_t; + +/* 9.11.3.8 5GS tracking area identity + * O TV 6 */ +typedef ogs_nas_tracking_area_identity_t ogs_nas_5gs_tracking_area_identity_t; + +/* 9.11.3.9 5GS tracking area identity list + * O TLV 9-114 */ +typedef ogs_nas_tracking_area_identity_list_t ogs_nas_5gs_tracking_area_identity_list_t; + +/* 9.11.3.9A 5GS update type + * O TLV 3 */ +typedef struct ogs_nas_5gs_update_type_s { + uint8_t length; +ED6(uint8_t spare:2;, + uint8_t pnb_ciot_eps:1;, + uint8_t pnb_ciot_5gs:1;, + uint8_t ng_ran_rcu:1;, + uint8_t sms_requested:1;, + uint8_t amf_pointer_value:2;) +} __attribute__ ((packed)) ogs_nas_5gs_update_type_t; + +/* 9.11.3.10 ABBA + * M LV 3-n */ +#define OGS_NAS_ABBA_LEN 255 +typedef struct ogs_nas_abba_s { + uint8_t length; + uint8_t abba[OGS_NAS_ABBA_LEN]; +} ogs_nas_abba_t; + +/* 9.11.3.11 Access Type + * M V 1/2 */ +#define OGS_NAS_NOTIFICATION_ACCESS_TYPE_3GPP 1 +#define OGS_NAS_NOTIFICATION_ACCESS_TYPE_NON_3GPP 2 +typedef struct ogs_nas_access_type_s { +ED2(uint8_t spare:5;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_access_type_t; + +/* 9.11.3.12 Additional 5G security information + * O TLV 3 */ +typedef struct ogs_nas_additional_5g_security_information_s { + uint8_t length; +ED3(uint8_t spare:6;, + uint8_t rinmr:1;, + uint8_t hdr:1;) +} __attribute__ ((packed)) ogs_nas_additional_5g_security_information_t; + +/* 9.11.3.12A Additional information requested + * O TLV 3 */ +typedef struct ogs_nas_additional_information_requested_s { + uint8_t length; +ED2(uint8_t spare:7;, + uint8_t cipher_key:1;) +} ogs_nas_additional_information_requested_t; + +/* 9.11.3.13 Allowed PDU session status + * O TLV 4-34 */ +typedef struct ogs_nas_allowed_pdu_session_status_s { + uint8_t length; +ED8(uint8_t psi7:1;, + uint8_t psi6:1;, + uint8_t psi5:1;, + uint8_t psi4:1;, + uint8_t psi3:1;, + uint8_t psi2:1;, + uint8_t psi1:1;, + uint8_t hdr0:1;) +ED8(uint8_t psi15:1;, + uint8_t psi14:1;, + uint8_t psi13:1;, + uint8_t psi12:1;, + uint8_t psi11:1;, + uint8_t psi10:1;, + uint8_t psi9:1;, + uint8_t psi8:1;) +} __attribute__ ((packed)) ogs_nas_allowed_pdu_session_status_t; + +/* 9.11.3.18 Configuration update indication + * O TV 1 */ +typedef struct ogs_nas_configuration_update_indication_s { +ED4(uint8_t type:4;, + uint8_t spare:2;, + uint8_t red:1;, + uint8_t ack:1;) +} __attribute__ ((packed)) ogs_nas_configuration_update_indication_t; + +/* 9.11.3.18A CAG information list + * O TLV-E 3-n */ +typedef struct ogs_nas_cag_information_list_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_cag_information_list_t; + +/* 9.11.3.18B CIoT small data container + * O TLV 4-257 */ +#define OGS_NAS_MAX_CIOT_SMALL_DATA_CONTAINER_LEN 254 +typedef struct ogs_nas_ciot_small_data_container_s { + uint8_t length; +ED3(uint8_t data_type:3;, + uint8_t ddx:2;, + uint8_t pdu_session_identity:1;) + uint8_t buffer[OGS_NAS_MAX_CIOT_SMALL_DATA_CONTAINER_LEN]; +} __attribute__ ((packed)) ogs_nas_ciot_small_data_container_t; + +/* 9.11.3.18C Ciphering key data + * O TLV-E x-n */ +typedef struct ogs_nas_ciphering_key_data_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_ciphering_key_data_t; + +/* 9.11.3.18D Control plane service type + * M V 1/2 */ +typedef struct ogs_nas_control_plane_service_type_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:1;) +} __attribute__ ((packed)) ogs_nas_control_plane_service_type_t; + +/* 9.11.3.20 De-registration type + * M V 1/2 */ +typedef struct ogs_nas_de_registration_type_s { +ED4(uint8_t type:4;, + uint8_t switch_off:1;, + uint8_t re_registration_required:1;, + uint8_t value:1;) +} __attribute__ ((packed)) ogs_nas_de_registration_type_t; + +/* 9.11.3.24 EPS NAS message container + * O TLV-E 4-n */ +typedef struct ogs_nas_eps_nas_message_container_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_eps_nas_message_container_t; + +/* 9.11.3.25 EPS NAS security algorithms + * O TV 2 */ +#define OGS_NAS_SECURITY_ALGORITHMS_EIA0 0 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EIA1 1 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EIA2 2 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EIA3 3 +#define OGS_NAS_SECURITY_ALGORITHMS_EEA0 0 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EEA1 1 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EEA2 2 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EEA3 3 +typedef struct ogs_nas_eps_nas_security_algorithms_s { +ED4(uint8_t spare1:1;, + uint8_t type_of_ciphering_algorithm:3;, + uint8_t spare2:1;, + uint8_t type_of_integrity_protection_algorithm:3;) +} __attribute__ ((packed)) ogs_nas_eps_nas_security_algorithms_t; + +/* 9.11.3.29 LADN indication + * O TLV-E 3-811 */ +typedef struct ogs_nas_ladn_indication_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_ladn_indication_t; + +/* 9.11.3.30 LADN information + * O TLV-E 12-1715 */ +typedef struct ogs_nas_ladn_information_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_ladn_information_t; + +/* 9.11.3.31 MICO indication + * O TV 1 */ +typedef struct ogs_nas_mico_indication_s { +ED3(uint8_t type:4;, + uint8_t spare:3;, + uint8_t raai:1;) +} __attribute__ ((packed)) ogs_nas_mico_indication_t; + +/* 9.11.3.31A MA PDU session information + * O TV 1 */ +typedef struct ogs_nas_ma_pdu_session_information_s { +ED2(uint8_t type:4;, + uint8_t value:4;) +} __attribute__ ((packed)) ogs_nas_ma_pdu_session_information_t; + +/* 9.11.3.31B Mapped NSSAI + * O TLV 3-42 */ +#define OGS_NAS_MAX_MAPPED_NSSAI_LEN 40 +typedef struct ogs_nas_mapped_nssai_s { + uint8_t length; + uint8_t buffer[OGS_NAS_MAX_MAPPED_NSSAI_LEN]; +} ogs_nas_mapped_nssai_t; + +/* 9.11.3.33 message container + * O TLV-E 4-n */ +typedef struct ogs_nas_message_container_s { + uint16_t length; + uint8_t *buffer; +} __attribute__ ((packed)) ogs_nas_message_container_t; + +/* 9.11.3.34 security algorithms + * M V 1 */ +#define OGS_NAS_SECURITY_ALGORITHMS_IA0 0 +#define OGS_NAS_SECURITY_ALGORITHMS_128_IA1 1 +#define OGS_NAS_SECURITY_ALGORITHMS_128_IA2 2 +#define OGS_NAS_SECURITY_ALGORITHMS_128_IA3 3 +#define OGS_NAS_SECURITY_ALGORITHMS_IA4 4 +#define OGS_NAS_SECURITY_ALGORITHMS_IA5 5 +#define OGS_NAS_SECURITY_ALGORITHMS_IA6 6 +#define OGS_NAS_SECURITY_ALGORITHMS_IA7 7 +#define OGS_NAS_SECURITY_ALGORITHMS_EA0 0 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EA1 1 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EA2 2 +#define OGS_NAS_SECURITY_ALGORITHMS_128_EA3 3 +#define OGS_NAS_SECURITY_ALGORITHMS_EA4 4 +#define OGS_NAS_SECURITY_ALGORITHMS_EA5 5 +#define OGS_NAS_SECURITY_ALGORITHMS_EA6 6 +#define OGS_NAS_SECURITY_ALGORITHMS_EA7 7 +typedef struct ogs_nas_security_algorithms_s { +ED4(uint8_t spare1:1;, + uint8_t type_of_ciphering_algorithm:3;, + uint8_t spare2:1;, + uint8_t type_of_integrity_protection_algorithm:3;) +} __attribute__ ((packed)) ogs_nas_security_algorithms_t; + +/* 9.11.3.36 Network slicing indication + * O TV 1 */ +typedef struct ogs_nas_network_slicing_indication_s { +ED4(uint8_t type:4;, + uint8_t spare:2;, + uint8_t dcni:1;, + uint8_t nssci:1;) +} __attribute__ ((packed)) ogs_nas_network_slicing_indication_t; + +/* 9.11.3.37 NSSAI + * O TLV 4-72 */ +#define MAX_NAS_NSSAI_LEN 72 +typedef struct ogs_nas_nssai_s { + uint8_t length; + uint8_t buffer[MAX_NAS_NSSAI_LEN]; +} __attribute__ ((packed)) ogs_nas_nssai_t; + +/* 9.11.3.37A NSSAI inclusion mode + * O TV 1 */ +#define OGS_NAS_NSSAI_INCLUSION_MODE_A 0 +#define OGS_NAS_NSSAI_INCLUSION_MODE_B 1 +#define OGS_NAS_NSSAI_INCLUSION_MODE_C 2 +#define OGS_NAS_NSSAI_INCLUSION_MODE_D 3 +typedef struct ogs_nas_nssai_inclusion_mode_s { +ED3(uint8_t type:4;, + uint8_t spare:2;, + uint8_t value:2;) +} __attribute__ ((packed)) ogs_nas_nssai_inclusion_mode_t; + +/* 9.11.3.38 Operator-defined access category definitions + * O TLV-E 3-n */ +typedef struct ogs_nas_operator_defined_access_category_definitions_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_operator_defined_access_category_definitions_t; + +/* 9.11.3.39 Payload container + * O TLV-E 4-65535 */ +typedef struct ogs_nas_payload_container_s { + uint16_t length; + uint8_t *buffer; +} ogs_nas_payload_container_t; + +/* 9.11.3.40 Payload container type + * O TV 1 */ +typedef struct ogs_nas_payload_container_type_s { +ED2(uint8_t type:4;, + uint8_t value:4;) +} __attribute__ ((packed)) ogs_nas_payload_container_type_t; + +/* 9.11.3.41 PDU session identity 2 + * C TV 2 */ +typedef struct ogs_nas_pdu_session_identity_2_s { + uint8_t type; + uint8_t value; +} __attribute__ ((packed)) ogs_nas_pdu_session_identity_2_t; + +/* 9.11.3.42 PDU session reactivation result + * O TLV 4-34 */ +typedef ogs_nas_allowed_pdu_session_status_t ogs_nas_pdu_session_reactivation_result_t; + +/* 9.11.3.43 PDU session reactivation result error cause + * O TLV-E 5-515 */ +typedef struct ogs_nas_pdu_session_reactivation_result_error_cause_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_pdu_session_reactivation_result_error_cause_t; + +/* 9.11.3.44 PDU session status + * O TLV 4-34 */ +typedef ogs_nas_allowed_pdu_session_status_t ogs_nas_pdu_session_status_t; + +/* 9.11.3.46 Rejected NSSAI + * O TLV 4-42 */ +#define OGS_MAX_NAS_REJECTED_NSSAI_LEN 40 +typedef struct ogs_nas_rejected_nssai_s { + uint8_t length; + uint8_t buffer[OGS_MAX_NAS_REJECTED_NSSAI_LEN]; +} ogs_nas_rejected_nssai_t; + +/* 9.11.3.47 Request type + * O TV 1 */ +#define OGS_NAS_REQUEST_TYPE_INITIAL 1 +#define OGS_NAS_REQUEST_TYPE_EXISTING_PDU_SESSION 2 +#define OGS_NAS_REQUEST_TYPE_INITIAL_EMERGENCY 3 +#define OGS_NAS_REQUEST_TYPE_EXISTING_PDU_SESSION_EMERGENCY 4 +#define OGS_NAS_REQUEST_TYPE_MODIFICATION 5 +typedef struct ogs_nas_request_type_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_request_type_t; + +/* 9.11.3.49 Service area list + * O TLV 6-114 */ +#define OGS_NAS_MAX_SERVICE_AREA_LIST_LEN 112 +typedef struct ogs_nas_service_area_list_s { + uint8_t length; + uint8_t buffer[112]; +} ogs_nas_service_area_list_t; + +/* 9.11.3.50 Service type + * M V 1/2 */ +#define OGS_NAS_SERVICE_TYPE_SIGNALLING 0 +#define OGS_NAS_SERVICE_TYPE_DATA 1 +#define OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES 2 +#define OGS_NAS_SERVICE_TYPE_EMERGENCY_SERVICES 3 +#define OGS_NAS_SERVICE_TYPE_EMERGENCY_SERVICES_FALLBACK 4 +#define OGS_NAS_SERVICE_TYPE_HIGH_PRIORITY_ACCESS 5 +#define OGS_NAS_SERVICE_TYPE_ELEVATED_SIGNALLING 6 +/* 7(unused) shall be interpreted as "signalling", if received by the network + * 8(unused) shall be interpreted as "signalling", if received by the network + * 9(unused) shall be interpreted as "signalling", if received by the network + * 10(unused) shall be interpreted as "data", if received by the network + * 11(unused) shall be interpreted as "data", if received by the network */ +typedef struct ogs_nas_service_type_s { +ED2(uint8_t type:4;, + uint8_t value:4;) +} __attribute__ ((packed)) ogs_nas_service_type_t; + +/* 9.11.3.50A SMS indication + * O TV 1 */ +typedef struct ogs_nas_sms_indication_s { +ED2(uint8_t type:4;, + uint8_t sai:4;) +} ogs_nas_sms_indication_t; + +/* 9.11.3.51 SOR transparent container + * O TLV-E 20-n */ +typedef struct ogs_nas_sor_transparent_container_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_sor_transparent_container_t; + +/* 9.11.3.54 UE security capability + * O TLV 4-10 */ +typedef struct ogs_nas_ue_security_capability_s { + uint8_t length; + union { + struct { + ED8(uint8_t ea0_5g:1;, + uint8_t ea1_5g_128:1;, + uint8_t ea2_5g_128:1;, + uint8_t ea3_5g_128:1;, + uint8_t ea4_5g:1;, + uint8_t ea5_5g:1;, + uint8_t ea6_5g:1;, + uint8_t ea7_5g:1;) + }; + uint8_t ea_5g; + }; + union { + struct { + ED8(uint8_t ia0_5g:1;, + uint8_t ia1_5g_128:1;, + uint8_t ia2_5g_128:1;, + uint8_t ia3_5g_128:1;, + uint8_t ia4_5g:1;, + uint8_t ia5_5g:1;, + uint8_t ia6_5g:1;, + uint8_t ia7_5g:1;) + }; + uint8_t ia_5g; + }; + union { + struct { + ED8(uint8_t eea0:1;, + uint8_t eea1_128:1;, + uint8_t eea2_128:1;, + uint8_t eea3_128:1;, + uint8_t eea4:1;, + uint8_t eea5:1;, + uint8_t eea6:1;, + uint8_t eea7:1;) + }; + uint8_t ea; + }; + union { + struct { + ED8(uint8_t eia0:1;, + uint8_t eia1_128:1;, + uint8_t eia2_128:1;, + uint8_t eia3_128:1;, + uint8_t eia4:1;, + uint8_t eia5:1;, + uint8_t eia6:1;, + uint8_t eia7:1;) + }; + uint8_t ia; + }; +} __attribute__ ((packed)) ogs_nas_ue_security_capability_t; + +/* 9.11.3.55 UE usage setting + * O TLV 3 */ +typedef struct ogs_nas_ue_usage_setting_s { + uint8_t length; +ED2(uint8_t spare:6;, + uint8_t value:2;) +} __attribute__ ((packed)) ogs_nas_ue_usage_setting_t; + +/* 9.11.3.56 UE status + * O TLV 3 */ +typedef struct ogs_nas_ue_status_s { + uint8_t length; +ED3(uint8_t spare:6;, + uint8_t n1:1;, + uint8_t s1:1;) +} __attribute__ ((packed)) ogs_nas_ue_status_t; + +/* 9.11.3.57 Uplink data status + * O TLV 4-34 */ +typedef ogs_nas_allowed_pdu_session_status_t ogs_nas_uplink_data_status_t; + +/* 9.11.3.68 UE radio capability ID + * O TLV 3-n */ +#define OGS_NAS_MAX_UE_RADIO_CAPABILITY_ID_LEN 255 +typedef struct ogs_nas_ue_radio_capability_id_s { + uint8_t length; + uint8_t buffer[OGS_NAS_MAX_UE_RADIO_CAPABILITY_ID_LEN]; +} ogs_nas_ue_radio_capability_id_t; + +/* 9.11.3.69 UE radio capability ID deletion infication + * O TV 1 */ +typedef struct ogs_nas_ue_radio_capability_id_deletion_indication_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_ue_radio_capability_id_deletion_indication_t; + +/* 9.11.3.70 Truncated 5G-S-TMSI configuration + * O TLV 3 */ +typedef struct ogs_nas_truncated_5g_s_tmsi_configuration_s { + uint8_t length; +ED2(uint8_t amf_set_id:4;, + uint8_t amf_pointer_value:4;) +} __attribute__ ((packed)) ogs_nas_truncated_5g_s_tmsi_configuration_t; + +/* 9.11.4.1 5GSM capability + * O TLV 3-15 */ +typedef struct ogs_nas_5gsm_capability_s { + uint8_t length; +ED3(uint8_t spare:6;, + uint8_t mh6_pdu:1;, + uint8_t rqos:1;) +} __attribute__ ((packed)) ogs_nas_5gsm_capability_t; + +/* 9.11.4.2 5GSM cause + * O TV 2 */ +#define OGS_NAS_GSM_OPERATOR_DETERMINED_BARRING 8 +#define OGS_NAS_GSM_INSUFFICIENT_RESOURCES 26 +#define OGS_NAS_GSM_MISSING_OR_UNKNOWN_DNN 27 +#define OGS_NAS_GSM_UNKNOWN_PDU_SESSION_TYPE 28 +#define OGS_NAS_GSM_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED 29 +#define OGS_NAS_GSM_REQUEST_REJECTED_UNSPECIFIED 31 +#define OGS_NAS_GSM_SERVICE_OPTION_NOT_SUPPORTED 32 +#define OGS_NAS_GSM_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED 33 +#define OGS_NAS_GSM_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER 34 +#define OGS_NAS_GSM_PTI_ALREADY_IN_USE 35 +#define OGS_NAS_GSM_REGULAR_DEACTIVATION 36 +#define OGS_NAS_GSM_NETWORK_FAILURE 38 +#define OGS_NAS_GSM_REACTIVATION_REQUESTED 39 +#define OGS_NAS_GSM_INVALID_PDU_SESSION_IDENTITY 43 +#define OGS_NAS_GSM_SEMANTIC_ERRORS_IN_PACKET_FILTERS 44 +#define OGS_NAS_GSM_SYNTACTICAL_ERROR_IN_PACKET_FILTERS 45 +#define OGS_NAS_GSM_OUT_OF_LADN_SERVICE_AREA 46 +#define OGS_NAS_GSM_PTI_MISMATCH 47 +#define OGS_NAS_GSM_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED 50 +#define OGS_NAS_GSM_PDU_SESSION_TYPE_IPV6_ONLY_ALLOWED 51 +#define OGS_NAS_GSM_PDU_SESSION_DOES_NOT_EXIST 54 +#define OGS_NAS_GSM_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN 67 +#define OGS_NAS_GSM_NOT_SUPPORTED_SSC_MODE 68 +#define OGS_NAS_GSM_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE 69 +#define OGS_NAS_GSM_MISSING_OR_UNKNOWN_DNN_IN_A_SLICE 70 +#define OGS_NAS_GSM_INVALID_PTI_VALUE 81 +#define OGS_NAS_GSM_MAXIMUM_DATA_RATE_PER_UE_FOR_USER_PLANE_INTEGRITY_PROTECTION_IS_TOO_LOW 82 +#define OGS_NAS_GSM_SEMANTIC_ERROR_IN_THE_QOS_OPERATION 83 +#define OGS_NAS_GSM_SYNTACTICAL_ERROR_IN_THE_QOS_OPERATION 84 +#define OGS_NAS_GSM_INVALID_MAPPED_EPS_BEARER_IDENTITY 85 +#define OGS_NAS_GSM_SEMANTICALLY_INCORRECT_MESSAGE 95 +#define OGS_NAS_GSM_INVALID_MANDATORY_INFORMATION 96 +#define OGS_NAS_GSM_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED 97 +#define OGS_NAS_GSM_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 98 +#define OGS_NAS_GSM_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT IMPLEMENTED 99 +#define OGS_NAS_GSM_CONDITIONAL_IE_ERROR 100 +#define OGS_NAS_GSM_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE 101 +#define OGS_NAS_GSM_PROTOCOL_ERROR_UNSPECIFIED 111 +typedef uint8_t ogs_nas_5gsm_cause_t; + +/* 9.11.4.21 5GSM congestion re-attempt indicator + * O TLV 3 */ +typedef struct ogs_nas_5gsm_congestion_re_attempt_indicator_s { + uint8_t length; +ED2(uint8_t spare:7;, + uint8_t abo:1;) +} __attribute__ ((packed)) ogs_nas_5gsm_congestion_re_attempt_indicator_t; + +/* 9.11.4.3 Always-on PDU session indication + * O TV 1 */ +typedef struct ogs_nas_always_on_pdu_session_indication_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t apsi:3;) +} __attribute__ ((packed)) ogs_nas_always_on_pdu_session_indication_t; + +/* 9.11.4.4 Always-on PDU session requested + * O TV 1 */ +typedef struct ogs_nas_always_on_pdu_session_requested_s { +ED3(uint8_t type:4;, + uint8_t spare:3;, + uint8_t apsr:1;) +} __attribute__ ((packed)) ogs_nas_always_on_pdu_session_requested_t; + +/* 9.11.4.5 Allowed SSC mode + * O TV 1 */ +typedef struct ogs_nas_allowed_ssc_mode_s { +ED5(uint8_t type:4;, + uint8_t spare:1;, + uint8_t ssc3:1;, + uint8_t ssc2:1;, + uint8_t ssc1:1;) +} __attribute__ ((packed)) ogs_nas_allowed_ssc_mode_t; + +/* 9.11.4.7 Integrity protection maximum data rate + * M V 2 */ +typedef struct ogs_nas_integrity_protection_maximum_data_rate_s { + uint8_t ul; + uint8_t dl; +} __attribute__ ((packed)) ogs_nas_integrity_protection_maximum_data_rate_t; + +/* 9.11.4.8 Mapped EPS bearer contexts + * O TLV-E 7-65535 */ +typedef struct ogs_nas_mapped_eps_bearer_contexts_s { + uint8_t length; + uint8_t *buffer; +} __attribute__ ((packed)) ogs_nas_mapped_eps_bearer_contexts_t; + +/* 9.11.4.9 Maximum number of supported packet filters + * O TV 3 */ +typedef struct ogs_nas_maximum_number_of_supported_packet_filters_s { + uint8_t max1; +ED2(uint8_t max2:3;, + uint8_t spare:5;) +} __attribute__ ((packed)) ogs_nas_maximum_number_of_supported_packet_filters_t; + +/* 9.11.4.10 PDU address + * O TLV 7, 11 or 15 */ +#define OGS_NAS_PDU_ADDRESS_TYPE_IPV4 1 +#define OGS_NAS_PDU_ADDRESS_TYPE_IPV6 2 +#define OGS_NAS_PDU_ADDRESS_TYPE_IPV4V6 3 +typedef struct ogs_nas_pdu_address_s { + uint8_t length; +ED2(uint8_t reserved:5;, + uint8_t type:3;) + union { + uint32_t addr; + struct { + uint8_t addr6[OGS_IPV6_LEN>>1]; /* Interface Identifer Only */ + }; + struct { + uint8_t addr6[OGS_IPV6_LEN>>1]; /* Interface Identifer Only */ + uint32_t addr; + } both; + }; +} __attribute__ ((packed)) ogs_nas_pdu_address_t; + +/* 9.11.4.11 PDU session type + * O TV 1 */ +#define OGS_NAS_PDU_SESSION_TYPE_IPV4 1 +#define OGS_NAS_PDU_SESSION_TYPE_IPV6 2 +#define OGS_NAS_PDU_SESSION_TYPE_IPV4V6 3 +#define OGS_NAS_PDU_SESSION_TYPE_UNSTRUCTURED 4 +#define OGS_NAS_PDU_SESSION_TYPE_ETHERNET 5 +typedef struct ogs_nas_pdu_session_type_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_pdu_session_type_t; + +/* 9.11.4.12 QoS flow descriptions + * O TLV-E 6-65535 */ +typedef struct ogs_nas_qos_flow_descriptions_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_qos_flow_descriptions_t; + +/* 9.11.4.13 QoS rules + * M LV-E 6-65535 */ +typedef struct ogs_nas_qos_rules_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_qos_rules_t; + +/* 9.11.4.14 Session-AMBR + * M LV 7 */ +#define OGS_NAS_BR_UNIT_1K 1 +#define OGS_NAS_BR_UNIT_4K 2 +#define OGS_NAS_BR_UNIT_16K 3 +#define OGS_NAS_BR_UNIT_64K 4 +#define OGS_NAS_BR_UNIT_256K 5 +#define OGS_NAS_BR_UNIT_1M 6 +#define OGS_NAS_BR_UNIT_4M 7 +#define OGS_NAS_BR_UNIT_16M 8 +#define OGS_NAS_BR_UNIT_64M 9 +#define OGS_NAS_BR_UNIT_256M 10 +#define OGS_NAS_BR_UNIT_1G 11 +#define OGS_NAS_BR_UNIT_4G 12 +#define OGS_NAS_BR_UNIT_16G 13 +#define OGS_NAS_BR_UNIT_64G 14 +#define OGS_NAS_BR_UNIT_256G 15 +#define OGS_NAS_BR_UNIT_1T 16 +#define OGS_NAS_BR_UNIT_4T 17 +#define OGS_NAS_BR_UNIT_16T 18 +#define OGS_NAS_BR_UNIT_64T 19 +#define OGS_NAS_BR_UNIT_256T 20 +#define OGS_NAS_BR_UNIT_1P 21 +#define OGS_NAS_BR_UNIT_4P 22 +#define OGS_NAS_BR_UNIT_16P 23 +#define OGS_NAS_BR_UNIT_64P 24 +#define OGS_NAS_BR_UNIT_256P 25 +typedef struct ogs_nas_session_ambr_s { + uint8_t length; + struct { + uint8_t unit; + uint16_t br; + } dl; + struct { + uint8_t unit; + uint16_t br; + } ul; +} __attribute__ ((packed)) ogs_nas_session_ambr_t; + +/* 9.11.4.15 SM PDU DN request container + * O TLV 3-255 */ +#define OGS_NAX_MAX_SM_PDU_DN_REQUESTER_CONTAINER 255 +typedef struct ogs_nas_sm_pdu_dn_request_container_s { + uint8_t length; + uint8_t buffer[OGS_NAX_MAX_SM_PDU_DN_REQUESTER_CONTAINER]; +} ogs_nas_sm_pdu_dn_request_container_t; + +/* 9.11.4.16 SSC mode + * O TV 1 */ +#define OGS_NAS_SSC_MODE_1 1 +#define OGS_NAS_SSC_MODE_2 2 +#define OGS_NAS_SSC_MODE_3 3 +/* 4(unused) shall be interpreted as "SSC mode 1", if received by the network */ +/* 5(unused) shall be interpreted as "SSC mode 2", if received by the network */ +/* 6(unused) shall be interpreted as "SSC mode 3", if received by the network */ +typedef struct ogs_nas_ssc_mode_s { +ED3(uint8_t type:4;, + uint8_t spare:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_ssc_mode_t; + +/* 9.11.4.18 5GSM network feature support + * O TLV 3-15 */ +typedef struct ogs_nas_5gsm_network_feature_support_s { + uint8_t length; +ED2(uint8_t spare:7;, + uint8_t s1:1;) +} __attribute__ ((packed)) ogs_nas_5gsm_network_feature_support_t; + +/* 9.11.4.22 ATSSS container + * O TLV-E 3-65535 */ +typedef struct ogs_nas_atsss_container_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_atsss_container_t; + +/* 9.9.4.25 Release assistance indication + * O TV 1 + * + * Release assistance indication value + * + * Downlink data expected (DDX) + * + * Bits + * 0 0 No information regarding DDX is conveyed by the information element. + * If received it shall be interpreted as 'neither value "01" nor "10" + * applies + * 0 1 No further uplink or downlink data transmission subsequent to the + * uplink data transmission is expected + * 1 0 Only a single downlink data transmission and no further uplink data + * transmission subsequent to the uplink data transmission is expected + * 1 1 reserved */ +typedef struct ogs_nas_release_assistance_indication_s { +ED3(uint8_t type:4;, + uint8_t spare:2;, + uint8_t value:2;) +} __attribute__ ((packed)) ogs_nas_release_assistance_indication_t; + +/* 9.11.4.25 DS-TT Ethernet port MAC address + * O TLV 8 */ +#define OGS_NAX_MAX_EHTERNET_MAC_ADDRESS_LEN 6 +typedef struct ogs_nas_ds_tt_ethernet_port_mac_address_s { + uint8_t length; + uint8_t buffer[OGS_NAX_MAX_EHTERNET_MAC_ADDRESS_LEN]; +} ogs_nas_ds_tt_ethernet_port_mac_address_t; + +/* 9.11.4.26 UE-DS-TT residence time + * O TLV 10 */ +#define OGS_NAS_MAX_UE_DS_TT_REDISENCE_TIME_LEN 8 +typedef struct ogs_nas_ue_ds_tt_residence_time_s { + uint8_t length; + uint8_t buffer[OGS_NAS_MAX_UE_DS_TT_REDISENCE_TIME_LEN]; +} ogs_nas_ue_ds_tt_residence_time_t; + +/* 9.11.4.27 Port management information container + * O TLV-E 4-65535 */ +typedef struct ogs_nas_port_management_information_container_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_port_management_information_container_t; + +/* 9.11.3.72 N5GC indication + * O T 1 */ +typedef struct ogs_nas_n5gc_indication_s { + uint8_t type; +} ogs_nas_n5gc_indication_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_5GS_TYPES_H */ diff --git a/lib/nas/conv.c b/lib/nas/common/conv.c similarity index 99% rename from lib/nas/conv.c rename to lib/nas/common/conv.c index 5b029a426..512604ce9 100644 --- a/lib/nas/conv.c +++ b/lib/nas/common/conv.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#include "ogs-nas.h" +#include "ogs-nas-common.h" void ogs_nas_imsi_to_bcd( ogs_nas_mobile_identity_imsi_t *imsi, uint8_t imsi_len, char *bcd) diff --git a/lib/nas/conv.h b/lib/nas/common/conv.h similarity index 91% rename from lib/nas/conv.h rename to lib/nas/common/conv.h index 31e95f8d2..6692a27f8 100644 --- a/lib/nas/conv.h +++ b/lib/nas/common/conv.h @@ -21,10 +21,10 @@ #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_CONV_H -#define OGS_NAS_CONV_H +#ifndef OGS_NAS_COMMON_CONV_H +#define OGS_NAS_COMMON_CONV_H -#include "ogs-nas.h" +#include "ogs-nas-common.h" #ifdef __cplusplus extern "C" { @@ -44,5 +44,5 @@ void ogs_nas_imeisv_to_bcd( } #endif -#endif /* OGS_NAS_CONV_H */ +#endif /* OGS_NAS_COMMON_CONV_H */ diff --git a/lib/nas/common/meson.build b/lib/nas/common/meson.build new file mode 100644 index 000000000..685caffe9 --- /dev/null +++ b/lib/nas/common/meson.build @@ -0,0 +1,36 @@ +# Copyright (C) 2019 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 . + +libnas_common_sources = files(''' + conv.c + types.c +'''.split()) + +libnas_common_inc = include_directories('.') + +libnas_common = library('ogsnas-common', + sources : libnas_common_sources, + version : libogslib_version, + c_args : '-DOGS_NAS_COMPILATION', + include_directories : [libnas_common_inc, libcrypt_inc, libinc], + dependencies : libcore_dep, + install : true) + +libnas_common_dep = declare_dependency( + link_with : libnas_common, + include_directories : [libnas_common_inc, libcrypt_inc, libinc], + dependencies : libcore_dep) diff --git a/lib/nas/ogs-nas.h b/lib/nas/common/ogs-nas-common.h similarity index 87% rename from lib/nas/ogs-nas.h rename to lib/nas/common/ogs-nas-common.h index 6e80897d2..5acdf65a6 100644 --- a/lib/nas/ogs-nas.h +++ b/lib/nas/common/ogs-nas-common.h @@ -17,18 +17,16 @@ * along with this program. If not, see . */ -#ifndef OGS_NAS_H -#define OGS_NAS_H +#ifndef OGS_NAS_COMMON_H +#define OGS_NAS_COMMON_H #include "ogs-core.h" #include "ogs-crypt.h" #define OGS_NAS_INSIDE -#include "nas/types.h" -#include "nas/conv.h" -#include "nas/ies.h" -#include "nas/message.h" +#include "nas/common/types.h" +#include "nas/common/conv.h" #undef OGS_NAS_INSIDE @@ -45,4 +43,4 @@ extern int __ogs_nas_domain; } #endif -#endif /* OGS_NAS_H */ +#endif /* OGS_NAS_COMMON_H */ diff --git a/lib/nas/types.c b/lib/nas/common/types.c similarity index 99% rename from lib/nas/types.c rename to lib/nas/common/types.c index 16b54455b..c35c157d0 100644 --- a/lib/nas/types.c +++ b/lib/nas/common/types.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#include "ogs-nas.h" +#include "ogs-nas-common.h" int __ogs_nas_domain; diff --git a/lib/nas/common/types.h b/lib/nas/common/types.h new file mode 100644 index 000000000..183c138b4 --- /dev/null +++ b/lib/nas/common/types.h @@ -0,0 +1,763 @@ +/* + * Copyright (C) 2019 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_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_NAS_COMMON_TYPES_H +#define OGS_NAS_COMMON_TYPES_H + +#include "ogs-core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define OGS_NAS_CLEAR_DATA(__dATA) \ + do { \ + ogs_assert((__dATA)); \ + if ((__dATA)->buffer) { \ + ogs_free((__dATA)->buffer); \ + (__dATA)->buffer = NULL; \ + (__dATA)->length = 0; \ + } \ + } while(0) +#define OGS_NAS_STORE_DATA(__dST, __sRC) \ + do { \ + ogs_assert((__sRC)); \ + ogs_assert((__sRC)->buffer); \ + ogs_assert((__dST)); \ + OGS_NAS_CLEAR_DATA(__dST); \ + (__dST)->length = (__sRC)->length; \ + (__dST)->buffer = ogs_calloc((__dST)->length, sizeof(uint8_t)); \ + memcpy((__dST)->buffer, (__sRC)->buffer, (__dST)->length); \ + } while(0) + +#define OGS_NAS_KSI_NO_KEY_IS_AVAILABLE 0x7 + +/********************************** + * NAS PLMN_ID Structure */ +typedef struct ogs_nas_plmn_id_s { +ED2(uint8_t mcc2:4;, + uint8_t mcc1:4;) +ED2(uint8_t mnc3:4;, + uint8_t mcc3:4;) +ED2(uint8_t mnc2:4;, + uint8_t mnc1:4;) +} __attribute__ ((packed)) ogs_nas_plmn_id_t; + +void *ogs_nas_from_plmn_id( + ogs_nas_plmn_id_t *ogs_nas_plmn_id, ogs_plmn_id_t *plmn_id); +void *ogs_nas_to_plmn_id( + ogs_plmn_id_t *plmn_id, ogs_nas_plmn_id_t *ogs_nas_plmn_id); + +typedef struct ogs_nas_guti_s { + ogs_nas_plmn_id_t nas_plmn_id; + uint16_t mme_gid; + uint8_t mme_code; + uint32_t m_tmsi; +} __attribute__ ((packed)) ogs_nas_guti_t; + +/* 9.9.2.0 Additional information + * O TLV 3-n */ +#define NAX_MAX_ADDITIONAL_INFORMATION_LEN 255 +typedef struct ogs_nas_additional_information_s { + uint8_t length; + uint8_t buffer[NAX_MAX_ADDITIONAL_INFORMATION_LEN]; +} __attribute__ ((packed)) ogs_nas_additional_information_t; + +/* 9.9.2.1 EPS bearer context status + * O TLV 4 */ +typedef struct ogs_nas_eps_bearer_context_status_s { + uint8_t length; +ED8(uint8_t ebi7:1;, + uint8_t ebi6:1;, + uint8_t ebi5:1;, + uint8_t ebi4:1;, + uint8_t ebi3:1;, + uint8_t ebi2:1;, + uint8_t ebi1:1;, + uint8_t ebi0:1;) +ED8(uint8_t ebi15:1;, + uint8_t ebi14:1;, + uint8_t ebi13:1;, + uint8_t ebi12:1;, + uint8_t ebi11:1;, + uint8_t ebi10:1;, + uint8_t ebi9:1;, + uint8_t ebi8:1;) +} __attribute__ ((packed)) ogs_nas_eps_bearer_context_status_t; + +/* 9.9.2.3 Mobile identity + * See subclause 10.5.1.4 in 3GPP TS 24.008 [13]. + * O TLV 7-10 */ +#define OGS_NAS_MOBILE_IDENTITY_NONE 0 +#define OGS_NAS_MOBILE_IDENTITY_IMSI 1 +#define OGS_NAS_MOBILE_IDENTITY_IMEI 2 +#define OGS_NAS_MOBILE_IDENTITY_IMEISV 3 +#define OGS_NAS_MOBILE_IDENTITY_TMSI 4 +#define OGS_NAS_MOBILE_IDENTITY_TMGI 5 +#define OGS_NAS_MOBILE_IDENTITY_GUTI 6 + +#define OGS_NAS_MOBILE_IDENTITY_EVEN 0 +#define OGS_NAS_MOBILE_IDENTITY_ODD 1 +typedef struct ogs_nas_mobile_identity_imsi_s { +ED3(uint8_t digit1:4;, + uint8_t odd_even:1;, + uint8_t type:3;) +ED2(uint8_t digit3:4;, + uint8_t digit2:4;) +ED2(uint8_t digit5:4;, + uint8_t digit4:4;) +ED2(uint8_t digit7:4;, + uint8_t digit6:4;) +ED2(uint8_t digit9:4;, + uint8_t digit8:4;) +ED2(uint8_t digit11:4;, + uint8_t digit10:4;) +ED2(uint8_t digit13:4;, + uint8_t digit12:4;) +ED2(uint8_t digit15:4;, + uint8_t digit14:4;) +} __attribute__ ((packed)) ogs_nas_mobile_identity_imsi_t; + +typedef ogs_nas_mobile_identity_imsi_t ogs_nas_mobile_identity_imei_t; + +typedef struct ogs_nas_mobile_identity_tmsi_s { +ED3(uint8_t spare:4;, + uint8_t odd_even:1;, + uint8_t type:3;) + uint32_t tmsi; +} __attribute__ ((packed)) ogs_nas_mobile_identity_tmsi_t; + +typedef struct ogs_nas_mobile_identity_tmgi_s { +ED5(uint8_t spare:2;, + uint8_t mbms_session_id:1;, + uint8_t mcc_mnc:1;, + uint8_t odd_even:1;, + uint8_t type:3;) + uint8_t mbms_servicec_id[3]; + ogs_nas_plmn_id_t nas_plmn_id; + uint8_t mbms_session_identity; +} __attribute__ ((packed)) ogs_nas_mobile_identity_tmgi_t; + +typedef struct ogs_nas_mobile_identity_imeisv_s { +ED3(uint8_t digit1:4;, + uint8_t odd_even:1;, + uint8_t type:3;) +ED2(uint8_t digit3:4;, + uint8_t digit2:4;) +ED2(uint8_t digit5:4;, + uint8_t digit4:4;) +ED2(uint8_t digit7:4;, + uint8_t digit6:4;) +ED2(uint8_t digit9:4;, + uint8_t digit8:4;) +ED2(uint8_t digit11:4;, + uint8_t digit10:4;) +ED2(uint8_t digit13:4;, + uint8_t digit12:4;) +ED2(uint8_t digit15:4;, + uint8_t digit14:4;) +ED2(uint8_t digit17:4;, + uint8_t digit16:4;) +} __attribute__ ((packed)) ogs_nas_mobile_identity_imeisv_t; + +typedef struct ogs_nas_mobile_identity_s { + uint8_t length; + union { + ogs_nas_mobile_identity_imsi_t imsi; + ogs_nas_mobile_identity_tmsi_t tmsi; + ogs_nas_mobile_identity_tmgi_t tmgi; + ogs_nas_mobile_identity_imeisv_t imeisv; + }; +} ogs_nas_mobile_identity_t; + +/* 9.9.2.4 Mobile station classmark 2 + * See subclause 10.5.1.6 in 3GPP TS 24.008 + * O TLV 5 */ +#define OGS_NAS_MS_CLASSMARK_2_REVISION_GSM_PHASE1 0 +#define OGS_NAS_MS_CLASSMARK_2_REVISION_GSM_PHASE2 1 +#define OGS_NAS_MS_CLASSMARK_2_REVISION_R99 2 +#define OGS_NAS_MS_CLASSMARK_2_REVISION_RESERVED 2 + +#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS1 0 +#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS2 1 +#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS3 2 +#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS4 3 +#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS5 4 +#define OGS_NAS_MS_CLASSMARK_2_RF_IRRELEVANT 7 +typedef struct ogs_nas_mobile_station_classmark_2_t { + uint8_t length; +ED5(uint8_t spare1:1;, + uint8_t revision_level:2;, + uint8_t es_ind:1;, + uint8_t a5_1:1;, + uint8_t rf_power_capability:3;) +ED7(uint8_t spare:1;, + uint8_t ps_capa:1;, + uint8_t ss_screen_indicator:2;, + uint8_t sm_capabi:1;, + uint8_t vbs:1;, + uint8_t vgcs:1;, + uint8_t fc:1;) +ED8(uint8_t cm3:1;, + uint8_t spare2:1;, + uint8_t lcsva_cap:1;, + uint8_t ucs2:1;, + uint8_t solsa:1;, + uint8_t cmsp:1;, + uint8_t a5_3:1;, + uint8_t a5_2:1;) +} __attribute__ ((packed)) ogs_nas_mobile_station_classmark_2_t; + +/* 9.9.2.8 PLMN list + * See subclause 10.5.1.13 in 3GPP TS 24.008 [13]. + * O TLV 5-47 */ +#define OGS_NAS_MAX_PLMN 15 +typedef struct ogs_nas_plmn_list_s { + uint8_t length; + ogs_nas_plmn_id_t nas_plmn_id[OGS_NAS_MAX_PLMN]; +} __attribute__ ((packed)) ogs_nas_plmn_list_t; + +/* 9.9.2.10 Supported codec list + * See subclause 10.5.4.32 in 3GPP TS 24.008 [13]. + * O TLV 5-n */ +typedef struct ogs_nas_supported_codec_item_s { + uint8_t system_identification; + uint8_t length_of_bitmap; + uint16_t codec_bitmap; +} __attribute__ ((packed)) ogs_nas_supported_codec_item_t; + +#define OGS_NAS_MAX_SUPPORTED_CODECS 8 +typedef struct ogs_nas_supported_codec_list_s { + uint8_t length; + ogs_nas_supported_codec_item_t item[OGS_NAS_MAX_SUPPORTED_CODECS]; +} __attribute__ ((packed)) ogs_nas_supported_codec_list_t; + +/* 9.9.3.1 Authentication failure parameter + * See subclause 10.5.3.2.2 in 3GPP TS 24.008 [13]. + * O TLV 16 */ +typedef struct ogs_nas_authentication_failure_parameter_s { + uint8_t length; + uint8_t auts[OGS_AUTS_LEN]; +} __attribute__ ((packed)) ogs_nas_authentication_failure_parameter_t; + +/* 9.9.3.2 Authentication parameter AUTN + * See subclause 10.5.3.1.1 in 3GPP TS 24.008 [13]. + * M LV 17 */ +typedef struct ogs_nas_authentication_parameter_autn_s { + uint8_t length; + uint8_t autn[OGS_AUTN_LEN]; +} ogs_nas_authentication_parameter_autn_t; + +/* 9.9.3.3 Authentication parameter RAND + * See subclause 10.5.3.1 in 3GPP TS 24.008 [13]. + * M V 16 */ +typedef struct ogs_nas_authentication_parameter_rand_s { + uint8_t rand[OGS_RAND_LEN]; +} ogs_nas_authentication_parameter_rand_t; + +/* 9.9.3.4 Authentication response parameter + * M LV 5-17 */ +typedef struct ogs_nas_authentication_response_parameter_s { + uint8_t length; + uint8_t res[OGS_MAX_RES_LEN]; +} ogs_nas_authentication_response_parameter_t; + +/* 9.9.3.6 Daylight saving time + * See subclause 10.5.3.12 in 3GPP TS 24.008 [13]. + * O TLV 3 */ +#define OGS_NAS_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 0 +#define OGS_NAS_PLUS_1_HOUR_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 1 +#define OGS_NAS_PLUS_2_HOURS_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 2 +typedef struct ogs_nas_daylight_saving_time_s { + uint8_t length; +ED2(uint8_t spare:6;, + uint8_t value:2;) +} __attribute__ ((packed)) ogs_nas_daylight_saving_time_t; + +/* 9.9.3.16 GPRS timer + * See subclause 10.5.7.3 in 3GPP TS 24.008 [13]. + * M V 1 or O TV 2 */ +#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_2_SS 0 +#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM 1 +#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH 2 +#define OGS_NAS_GRPS_TIMER_UNIT_DEACTIVATED 7 +typedef struct ogs_nas_gprs_timer_s { +ED2(uint8_t unit:3;, + uint8_t value:5;) +} __attribute__ ((packed)) ogs_nas_gprs_timer_t; + +/* 9.9.3.16A GPRS timer 2 + * See subclause 10.5.7.4 in 3GPP TS 24.008 [13]. + * O TLV 3 */ +typedef struct ogs_nas_gprs_timer_2_s { + uint8_t length; + uint8_t gprs_timer_2_value; +} __attribute__ ((packed)) ogs_nas_gprs_timer_2_t; + +/* 9.9.3.16B GPRS timer 3 + * See subclause 10.5.7.4a in 3GPP TS 24.008 [13]. + * O TLV 3 */ +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_MM 0 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_HH 1 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_HH 2 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_2_SS 3 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_30_SS 4 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_MM 5 +#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_320_HH 6 +#define OGS_NAS_GRPS_TIMER_3_UNIT_DEACTIVATED 7 + +typedef struct ogs_nas_gprs_timer_3_s { + uint8_t length; +ED2(uint8_t unit:3;, + uint8_t timer_value:5;) +} __attribute__ ((packed)) ogs_nas_gprs_timer_3_t; + +/* 9.9.3.18 IMEISV request + * See subclause 10.5.5.10 in 3GPP TS 24.008 [13]. + * O TV 1 */ +typedef struct ogs_nas_imeisv_request_s { +#define OGS_NAS_IMEISV_TYPE 0xc +ED3(uint8_t type:4;, + uint8_t spare:1;, +#define OGS_NAS_IMEISV_NOT_REQUESTED 0 +#define OGS_NAS_IMEISV_REQUESTED 1 + uint8_t imeisv_request_value:3;) +} __attribute__ ((packed)) ogs_nas_imeisv_request_t; + +/* 9.9.3.21 NAS key set identifier + * M V 1/2 + * 9.9.2.9 Spare half octet + * M V 1/2 */ +typedef struct ogs_nas_key_set_identifier_s { +ED3(uint8_t type:4;, + uint8_t tsc:1;, + uint8_t value:3;) +} __attribute__ ((packed)) ogs_nas_key_set_identifier_t; + +/* 9.9.3.24 Network name + * See subclause 10.5.3.5a in 3GPP TS 24.008 [13]. + * O TLV 3-n */ +#define OGS_NAS_MAX_NETWORK_NAME_LEN 255 +typedef struct ogs_nas_network_name_s { + uint8_t length; +ED4(uint8_t ext:1;, + uint8_t coding_scheme:3;, + uint8_t add_ci:1;, + uint8_t number_of_spare_bits_in_last_octet:3;) + uint8_t name[OGS_NAS_MAX_NETWORK_NAME_LEN]; +} __attribute__ ((packed)) ogs_nas_network_name_t; + +/* 9.9.3.29 Time zone + * See subclause 10.5.3.8 in 3GPP TS 24.008 [13]. + * O TV 2 */ +typedef uint8_t ogs_nas_time_zone_t; + +/* 9.9.3.30 Time zone and time + * See subclause 10.5.3.9 in 3GPP TS 24.008 [13]. + * 9.2.3.11 TPServiceCentreTimeStamp (TPSCTS) in 3GPP TS 23.040 [90] + * O TV 8 */ +#define OGS_OGS_NAS_TIME_TO_BCD(x) OGS_TIME_TO_BCD(x) +typedef struct ogs_nas_time_zone_and_time_s { + uint8_t year; + uint8_t mon; + uint8_t mday; + uint8_t hour; + uint8_t min; + uint8_t sec; + /* The Time Zone indicates the difference, expressed in quarters of an hour, + * between the local time and GMT. In the first of the two semi-octets, + * the first bit (bit 3 of the seventh octet of + * the TP-Service-Centre-Time-Stamp field) represents + * the algebraic sign of this difference (0: positive, 1: negative). */ + uint8_t timezone; +} ogs_nas_time_zone_and_time_t; + +/* 9.9.3.32 Tracking area identity + * O TV 6 */ +typedef struct ogs_nas_tracking_area_identity_s { + ogs_nas_plmn_id_t nas_plmn_id; + uint16_t tac; +} __attribute__ ((packed)) ogs_nas_tracking_area_identity_t; + +typedef ogs_nas_tracking_area_identity_t ogs_nas_tai_t; + +/* 9.9.3.33 Tracking area identity list + * M LV 7-97 */ +#define OGS_NAS_MAX_TAI_LIST_LEN 96 +#define TAI0_TYPE 0 +#define TAI1_TYPE 1 +#define TAI2_TYPE 2 +typedef struct tai0_list_s { + struct { + ED3(uint8_t spare:1;, + uint8_t type:2;, + uint8_t num:5;) + /* + * Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'. + * Use 'ogs_plmn_id_t' for easy implementation. + * ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t) + * and is sent to the UE. + */ + ogs_plmn_id_t plmn_id; + uint16_t tac[OGS_MAX_NUM_OF_TAI]; + } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; +} __attribute__ ((packed)) tai0_list_t; + +typedef struct tai2_list_s { +ED3(uint8_t spare:1;, + uint8_t type:2;, + uint8_t num:5;) + /* + * Do not change 'ogs_tai_t' to 'ogs_nas_tracking_area_identity_t'. + * Use 'ogs_tai_t' for easy implementation. + * ogs_nas_tai_list_build() changes to NAS + * format(ogs_nas_tracking_area_identity_t) + * and is sent to the UE. + */ + ogs_tai_t tai[OGS_MAX_NUM_OF_TAI]; +} __attribute__ ((packed)) tai2_list_t; + +typedef struct ogs_nas_tracking_area_identity_list_s { + uint8_t length; + uint8_t buffer[OGS_NAS_MAX_TAI_LIST_LEN]; +} __attribute__ ((packed)) ogs_nas_tracking_area_identity_list_t; + +void ogs_nas_tai_list_build( + ogs_nas_tracking_area_identity_list_t *target, + tai0_list_t *source0, tai2_list_t *source2); + +/* 9.9.3.34 UE network capability + * M LV 3-14 */ +typedef struct ogs_nas_s1_ue_network_capability_s { + uint8_t length; + union { + struct { + ED8(uint8_t eea0:1;, + uint8_t eea1:1;, + uint8_t eea2:1;, + uint8_t eea3:1;, + uint8_t eea4:1;, + uint8_t eea5:1;, + uint8_t eea6:1;, + uint8_t eea7:1;) + }; + uint8_t eea; + }; + union { + struct { + ED8(uint8_t eia0:1;, + uint8_t eia1:1;, + uint8_t eia2:1;, + uint8_t eia3:1;, + uint8_t eia4:1;, + uint8_t eia5:1;, + uint8_t eia6:1;, + uint8_t eia7:1;) + }; + uint8_t eia; + }; + union { + struct { + ED8(uint8_t uea0:1;, + uint8_t uea1:1;, + uint8_t uea2:1;, + uint8_t uea3:1;, + uint8_t uea4:1;, + uint8_t uea5:1;, + uint8_t uea6:1;, + uint8_t uea7:1;) + }; + uint8_t uea; + }; + union { + struct { + ED8(uint8_t ucs2:1;, + uint8_t uia1:1;, + uint8_t uia2:1;, + uint8_t uia3:1;, + uint8_t uia4:1;, + uint8_t uia5:1;, + uint8_t uia6:1;, + uint8_t uia7:1;) + }; + uint8_t uia; + }; +ED8(uint8_t prose_dd:1;, + uint8_t prose:1;, + uint8_t h_245_ash:1;, + uint8_t acc_csfb:1;, + uint8_t lpp:1;, + uint8_t lcs:1;, + uint8_t srvcc:1;, + uint8_t nf:1;) +ED8(uint8_t epco:1;, + uint8_t hc_cp_ciot:1;, + uint8_t erw_opdn:1;, + uint8_t s1u_data:1;, + uint8_t up_ciot:1;, + uint8_t cp_ciot:1;, + uint8_t prose_relay:1;, + uint8_t prose_dc:1;) +ED2(uint8_t spare:7;, + uint8_t multiple_drb:1;) +} __attribute__ ((packed)) ogs_nas_s1_ue_network_capability_t; + +/* 9.9.3.36 UE security capability + * M LV 3-6 */ +typedef struct ogs_nas_s1_ue_security_capability_s { + uint8_t length; + union { + struct { + ED8(uint8_t eea0:1;, + uint8_t eea1:1;, + uint8_t eea2:1;, + uint8_t eea3:1;, + uint8_t eea4:1;, + uint8_t eea5:1;, + uint8_t eea6:1;, + uint8_t eea7:1;) + }; + uint8_t eea; + }; + union { + struct { + ED8(uint8_t eia0:1;, + uint8_t eia1:1;, + uint8_t eia2:1;, + uint8_t eia3:1;, + uint8_t eia4:1;, + uint8_t eia5:1;, + uint8_t eia6:1;, + uint8_t eia7:1;) + }; + uint8_t eia; + }; + union { + struct { + ED8(uint8_t uea0:1;, + uint8_t uea1:1;, + uint8_t uea2:1;, + uint8_t uea3:1;, + uint8_t uea4:1;, + uint8_t uea5:1;, + uint8_t uea6:1;, + uint8_t uea7:1;) + }; + uint8_t uea; + }; + union { + struct { + ED8(uint8_t spare1:1;, + uint8_t uia1:1;, + uint8_t uia2:1;, + uint8_t uia3:1;, + uint8_t uia4:1;, + uint8_t uia5:1;, + uint8_t uia6:1;, + uint8_t uia7:1;) + }; + uint8_t uia; + }; + union { + struct { + ED8(uint8_t spare2:1;, + uint8_t gea1:1;, + uint8_t gea2:1;, + uint8_t gea3:1;, + uint8_t gea4:1;, + uint8_t gea5:1;, + uint8_t gea6:1;, + uint8_t gea7:1;) + }; + uint8_t gea; + }; +} __attribute__ ((packed)) ogs_nas_s1_ue_security_capability_t; + +/* 9.9.3.62 WUS assistance information + * O TLV 3-n */ +#define OGS_MAX_NAS_WUS_ASSISTANCE_INFORAMTION_LEN 255 +typedef struct ogs_nas_wus_assistance_information_s { + uint8_t length; + uint8_t buffer[OGS_MAX_NAS_WUS_ASSISTANCE_INFORAMTION_LEN]; +} ogs_nas_wus_assistance_information_t; + +/* 9.11.3.36A Non-3GPP NW provided policies + * See subclause 10.5.5.37 in 3GPP TS 24.008 [12]. + * O TV 1 */ +typedef struct ogs_nas_non_3gpp_nw_provided_policies_s { +ED3(uint8_t type:4;, + uint8_t apre:3;, + uint8_t value:3;) +} ogs_nas_non_3gpp_nw_provided_policies_t; + +/* buffer : 9.9.3.37 Emergency number list + * See subclause 10.5.3.13 in 3GPP TS 24.008 [13]. + * O TLV 5-50 */ +#define OGS_NAS_MAX_EMERGENCY_NUMBER_LIST_LEN 48 +typedef struct ogs_nas_emergency_number_list_s { + uint16_t length; + uint8_t buffer[OGS_NAS_MAX_EMERGENCY_NUMBER_LIST_LEN]; +} __attribute__ ((packed)) ogs_nas_emergency_number_list_t; + +/* 9.9.3.37A Extended emergency number list + * O TLV-E 7-65535 */ +typedef struct ogs_nas_extended_emergency_number_list_s { + uint8_t length; + uint8_t *buffer; +} ogs_nas_extended_emergency_number_list_t; + +/* 9.9.3.46 Extended DRX parameters + * See subclause 10.5.5.32 in 3GPP TS 24.008 [13]. + * O TLV 3 */ +typedef struct ogs_nas_extended_drx_parameters_s { + uint8_t length; +ED2(uint8_t paging_time_window:4;, + uint8_t e_drx_value:4;) +} __attribute__ ((packed)) ogs_nas_extended_drx_parameters_t; + +/* 9.9.4.2 APN aggregate maximum bit rate + * O TLV 4-8 */ +typedef struct ogs_nas_apn_aggregate_maximum_bit_rate_s { + uint8_t length; + uint8_t dl_apn_ambr; + uint8_t ul_apn_ambr; + uint8_t dl_apn_ambr_extended; + uint8_t ul_apn_ambr_extended; + uint8_t dl_apn_ambr_extended2; + uint8_t ul_apn_ambr_extended2; +} __attribute__ ((packed)) ogs_nas_apn_aggregate_maximum_bit_rate_t; + +void apn_ambr_build( + ogs_nas_apn_aggregate_maximum_bit_rate_t * apn_aggregate_maximum_bit_rate, + uint32_t dl_ambr, uint32_t ul_ambr); + +/* 9.9.4.3 EPS quality of service + * M LV 2-14 */ +typedef struct ogs_nas_eps_quality_of_service_s { + uint8_t length; + uint8_t qci; + uint8_t ul_mbr; + uint8_t dl_mbr; + uint8_t ul_gbr; + uint8_t dl_gbr; + uint8_t ul_mbr_extended; + uint8_t dl_mbr_extended; + uint8_t ul_gbr_extended; + uint8_t dl_gbr_extended; + uint8_t ul_mbr_extended2; + uint8_t dl_mbr_extended2; + uint8_t ul_gbr_extended2; + uint8_t dl_gbr_extended2; +} ogs_nas_eps_quality_of_service_t; + +void eps_qos_build(ogs_nas_eps_quality_of_service_t *eps_qos, + uint8_t qci, + uint64_t dl_mbr, uint64_t ul_mbr, uint64_t dl_gbr, uint64_t ul_gbr); + +/* 9.9.4.13A Re-attempt indicator + * O TLV 3 */ +typedef struct ogs_nas_re_attempt_indicator_s { + uint8_t length; +ED3(uint8_t spare:3;, /* allowed in A/Gb mode or Iu mode */ + uint8_t eplmnc:1;, /* allowed in an equivalent PLMN */ + uint8_t ratc:1;) +} __attribute__ ((packed)) ogs_nas_re_attempt_indicator_t; + +/* 9.9.4.19 NBIFOM container + * See subclause 10.5.6.21 in 3GPP TS 24.008 [4]. + * O TLV 3-257 */ +#define MAX_OGS_NAS_NBIFOM_CONTAINER_LEN 255 +typedef struct ogs_nas_nbifom_container_s { + uint8_t length; + uint8_t buffer[MAX_OGS_NAS_NBIFOM_CONTAINER_LEN]; +} __attribute__ ((packed)) ogs_nas_nbifom_container_t; + +/* 9.9.4.22 Header compression configuration + * O TLV 5-257 */ +#define MAX_OGS_NAS_HEADER_COMPRESSION_CONTAINER_LEN 251 +typedef struct ogs_nas_header_compression_configuration_s { + uint8_t length; +ED8(uint8_t spare:1;, + uint8_t profile0x0104:1;, + uint8_t profile0x0103:1;, + uint8_t profile0x0102:1;, + uint8_t profile0x0006:1;, + uint8_t profile0x0004:1;, + uint8_t profile0x0003:1;, + uint8_t profile0x0002:1;) + uint16_t max_cid; +#define OGS_NAS_HEADER_COMPRESSION_NO_COMPRESSION 0 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0002_UDP_IP 1 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0003_ESP_IP 2 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0004 3 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0006 4 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0102_UDP_IP 5 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0103_ESP_IP 6 +#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0104_IP 7 + uint8_t type; + uint8_t container[MAX_OGS_NAS_NBIFOM_CONTAINER_LEN]; +} __attribute__ ((packed)) ogs_nas_header_compression_configuration_t; + +/* 9.9.4.23 Control plane only indication + * O TV 1 */ +typedef struct ogs_nas_control_plane_only_indication_s { +ED3(uint8_t type:4;, + uint8_t spare:3;, + uint8_t ciot_eps_optimization:1;) +} __attribute__ ((packed)) ogs_nas_control_plane_only_indication_t; + +/* 9.9.4.26 Extended protocol configuration options + * See subclause 10.5.6.3A in 3GPP TS 24.008 [12] + * O TLV-E 4-65538 */ +typedef struct ogs_nas_extended_protocol_configuration_options_s { + uint16_t length; + uint8_t *buffer; +} __attribute__ ((packed)) ogs_nas_extended_protocol_configuration_options_t; + +/* 9.9.4.28 Serving PLMN rate control + * O TLV 4 */ +typedef struct ogs_nas_serving_plmn_rate_control_s { + uint8_t length; +ED8(uint8_t ebi7:1;, + uint8_t ebi6:1;, + uint8_t ebi5:1;, + uint8_t ebi4:1;, + uint8_t ebi3:1;, + uint8_t ebi2:1;, + uint8_t ebi1:1;, + uint8_t ebi0:1;) +ED8(uint8_t ebi15:1;, + uint8_t ebi14:1;, + uint8_t ebi13:1;, + uint8_t ebi12:1;, + uint8_t ebi11:1;, + uint8_t ebi10:1;, + uint8_t ebi9:1;, + uint8_t ebi8:1;) +} __attribute__ ((packed)) ogs_nas_serving_plmn_rate_control_t; + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_COMMON_TYPES_H */ diff --git a/lib/nas/decoder.c b/lib/nas/decoder.c deleted file mode 100644 index 82b47e7d7..000000000 --- a/lib/nas/decoder.c +++ /dev/null @@ -1,3030 +0,0 @@ -/* - * The MIT License - * - * Copyright (C) 2019,2020 by Sukchan Lee - * - * This file is part of Open5GS. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/******************************************************************************* - * 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: 2020-04-24 08:50:31.643694 by acetcom - * from 24301-d80.docx - ******************************************************************************/ - -#include "ogs-nas.h" - -int ogs_nas_decode_attach_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_attach_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_attach_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_attach_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_detach_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_detach_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_tracking_area_update_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_tracking_area_update_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_tracking_area_update_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_extended_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_guti_reallocation_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_emm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_emm_information(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_downlink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_uplink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_cs_service_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_uplink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_downlink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_default_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_default_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_default_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_dedicated_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_modify_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_modify_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_modify_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_deactivate_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_deactivate_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_pdn_connectivity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_pdn_connectivity_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_pdn_disconnect_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_pdn_disconnect_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_bearer_resource_allocation_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_bearer_resource_allocation_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_bearer_resource_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_bearer_resource_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_esm_information_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_esm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); -int ogs_nas_decode_attach_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_attach_request_t *attach_request = &message->emm.attach_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ATTACH_REQUEST\n"); - - size = ogs_nas_decode_eps_attach_type(&attach_request->eps_attach_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_eps_mobile_identity(&attach_request->eps_mobile_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_ue_network_capability(&attach_request->ue_network_capability, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_esm_message_container(&attach_request->esm_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE: - size = ogs_nas_decode_p_tmsi_signature(&attach_request->old_p_tmsi_signature, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_TYPE: - size = ogs_nas_decode_eps_mobile_identity(&attach_request->additional_guti, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE: - size = ogs_nas_decode_tracking_area_identity(&attach_request->last_visited_registered_tai, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_TYPE: - size = ogs_nas_decode_drx_parameter(&attach_request->drx_parameter, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_TYPE: - size = ogs_nas_decode_ms_network_capability(&attach_request->ms_network_capability, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE: - size = ogs_nas_decode_location_area_identification(&attach_request->old_location_area_identification, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_TYPE: - size = ogs_nas_decode_tmsi_status(&attach_request->tmsi_status, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE: - size = ogs_nas_decode_mobile_station_classmark_2(&attach_request->mobile_station_classmark_2, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE: - size = ogs_nas_decode_mobile_station_classmark_3(&attach_request->mobile_station_classmark_3, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_TYPE: - size = ogs_nas_decode_supported_codec_list(&attach_request->supported_codecs, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE: - size = ogs_nas_decode_additional_update_type(&attach_request->additional_update_type, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE: - size = ogs_nas_decode_voice_domain_preference_and_ue_usage_setting(&attach_request->voice_domain_preference_and_ue_usage_setting, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&attach_request->device_properties, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_TYPE: - size = ogs_nas_decode_guti_type(&attach_request->old_guti_type, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE: - size = ogs_nas_decode_ms_network_feature_support(&attach_request->ms_network_feature_support, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE: - size = ogs_nas_decode_network_resource_identifier_container(&attach_request->tmsi_based_nri_container, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_T3324_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&attach_request->t3324_value, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_T3324_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&attach_request->t3412_extended_value, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE: - size = ogs_nas_decode_extended_drx_parameters(&attach_request->extended_drx_parameters, pkbuf); - ogs_assert(size >= 0); - attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_attach_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_attach_accept_t *attach_accept = &message->emm.attach_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ATTACH_ACCEPT\n"); - - size = ogs_nas_decode_eps_attach_result(&attach_accept->eps_attach_result, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_gprs_timer(&attach_accept->t3412_value, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_tracking_area_identity_list(&attach_accept->tai_list, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_esm_message_container(&attach_accept->esm_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ATTACH_ACCEPT_GUTI_TYPE: - size = ogs_nas_decode_eps_mobile_identity(&attach_accept->guti, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_GUTI_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE: - size = ogs_nas_decode_location_area_identification(&attach_accept->location_area_identification, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_TYPE: - size = ogs_nas_decode_mobile_identity(&attach_accept->ms_identity, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_TYPE: - size = ogs_nas_decode_emm_cause(&attach_accept->emm_cause, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer(&attach_accept->t3402_value, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer(&attach_accept->t3423_value, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_TYPE: - size = ogs_nas_decode_plmn_list(&attach_accept->equivalent_plmns, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE: - size = ogs_nas_decode_emergency_number_list(&attach_accept->emergency_number_list, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE: - size = ogs_nas_decode_eps_network_feature_support(&attach_accept->eps_network_feature_support, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE: - size = ogs_nas_decode_additional_update_result(&attach_accept->additional_update_result, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&attach_accept->t3412_extended_value, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&attach_accept->t3324_value, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE: - size = ogs_nas_decode_extended_drx_parameters(&attach_accept->extended_drx_parameters, pkbuf); - ogs_assert(size >= 0); - attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_attach_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_attach_complete_t *attach_complete = &message->emm.attach_complete; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ATTACH_COMPLETE\n"); - - size = ogs_nas_decode_esm_message_container(&attach_complete->esm_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_attach_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_attach_reject_t *attach_reject = &message->emm.attach_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ATTACH_REJECT\n"); - - size = ogs_nas_decode_emm_cause(&attach_reject->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_TYPE: - size = ogs_nas_decode_esm_message_container(&attach_reject->esm_message_container, pkbuf); - ogs_assert(size >= 0); - attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REJECT_T3346_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&attach_reject->t3346_value, pkbuf); - ogs_assert(size >= 0); - attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_T3346_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REJECT_T3402_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&attach_reject->t3402_value, pkbuf); - ogs_assert(size >= 0); - attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_T3402_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_TYPE: - size = ogs_nas_decode_extended_emm_cause(&attach_reject->extended_emm_cause, pkbuf); - ogs_assert(size >= 0); - attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_detach_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_detach_request_from_ue_t *detach_request_from_ue = &message->emm.detach_request_from_ue; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DETACH_REQUEST\n"); - - size = ogs_nas_decode_detach_type(&detach_request_from_ue->detach_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_eps_mobile_identity(&detach_request_from_ue->eps_mobile_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_detach_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_detach_request_to_ue_t *detach_request_to_ue = &message->emm.detach_request_to_ue; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DETACH_REQUEST\n"); - - size = ogs_nas_decode_detach_type(&detach_request_to_ue->detach_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_DETACH_REQUEST_EMM_CAUSE_TYPE: - size = ogs_nas_decode_emm_cause(&detach_request_to_ue->emm_cause, pkbuf); - ogs_assert(size >= 0); - detach_request_to_ue->presencemask |= OGS_NAS_DETACH_REQUEST_EMM_CAUSE_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_tracking_area_update_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_tracking_area_update_request_t *tracking_area_update_request = &message->emm.tracking_area_update_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_REQUEST\n"); - - size = ogs_nas_decode_eps_update_type(&tracking_area_update_request->eps_update_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_request->old_guti, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE: - size = ogs_nas_decode_key_set_identifier(&tracking_area_update_request->non_current_native_nas_key_set_identifier, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_TYPE: - size = ogs_nas_decode_ciphering_key_sequence_number(&tracking_area_update_request->gprs_ciphering_key_sequence_number, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE: - size = ogs_nas_decode_p_tmsi_signature(&tracking_area_update_request->old_p_tmsi_signature, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_TYPE: - size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_request->additional_guti, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_TYPE: - size = ogs_nas_decode_nonce(&tracking_area_update_request->nonceue, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_TYPE: - size = ogs_nas_decode_ue_network_capability(&tracking_area_update_request->ue_network_capability, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE: - size = ogs_nas_decode_tracking_area_identity(&tracking_area_update_request->last_visited_registered_tai, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_TYPE: - size = ogs_nas_decode_drx_parameter(&tracking_area_update_request->drx_parameter, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_TYPE: - size = ogs_nas_decode_ue_radio_capability_information_update_needed(&tracking_area_update_request->ue_radio_capability_information_update_needed, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE: - size = ogs_nas_decode_eps_bearer_context_status(&tracking_area_update_request->eps_bearer_context_status, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_TYPE: - size = ogs_nas_decode_ms_network_capability(&tracking_area_update_request->ms_network_capability, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE: - size = ogs_nas_decode_location_area_identification(&tracking_area_update_request->old_location_area_identification, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_TYPE: - size = ogs_nas_decode_tmsi_status(&tracking_area_update_request->tmsi_status, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE: - size = ogs_nas_decode_mobile_station_classmark_2(&tracking_area_update_request->mobile_station_classmark_2, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE: - size = ogs_nas_decode_mobile_station_classmark_3(&tracking_area_update_request->mobile_station_classmark_3, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_TYPE: - size = ogs_nas_decode_supported_codec_list(&tracking_area_update_request->supported_codecs, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE: - size = ogs_nas_decode_additional_update_type(&tracking_area_update_request->additional_update_type, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE: - size = ogs_nas_decode_voice_domain_preference_and_ue_usage_setting(&tracking_area_update_request->voice_domain_preference_and_ue_usage_setting, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_TYPE: - size = ogs_nas_decode_guti_type(&tracking_area_update_request->old_guti_type, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&tracking_area_update_request->device_properties, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE: - size = ogs_nas_decode_ms_network_feature_support(&tracking_area_update_request->ms_network_feature_support, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE: - size = ogs_nas_decode_network_resource_identifier_container(&tracking_area_update_request->tmsi_based_nri_container, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_request->t3324_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&tracking_area_update_request->t3412_extended_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE: - size = ogs_nas_decode_extended_drx_parameters(&tracking_area_update_request->extended_drx_parameters, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_tracking_area_update_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_tracking_area_update_accept_t *tracking_area_update_accept = &message->emm.tracking_area_update_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_ACCEPT\n"); - - size = ogs_nas_decode_eps_update_result(&tracking_area_update_accept->eps_update_result, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3412_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_TYPE: - size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_accept->guti, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_TYPE: - size = ogs_nas_decode_tracking_area_identity_list(&tracking_area_update_accept->tai_list, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE: - size = ogs_nas_decode_eps_bearer_context_status(&tracking_area_update_accept->eps_bearer_context_status, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE: - size = ogs_nas_decode_location_area_identification(&tracking_area_update_accept->location_area_identification, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_TYPE: - size = ogs_nas_decode_mobile_identity(&tracking_area_update_accept->ms_identity, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_TYPE: - size = ogs_nas_decode_emm_cause(&tracking_area_update_accept->emm_cause, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3402_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3423_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_TYPE: - size = ogs_nas_decode_plmn_list(&tracking_area_update_accept->equivalent_plmns, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE: - size = ogs_nas_decode_emergency_number_list(&tracking_area_update_accept->emergency_number_list, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE: - size = ogs_nas_decode_eps_network_feature_support(&tracking_area_update_accept->eps_network_feature_support, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE: - size = ogs_nas_decode_additional_update_result(&tracking_area_update_accept->additional_update_result, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&tracking_area_update_accept->t3412_extended_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_accept->t3324_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE: - size = ogs_nas_decode_extended_drx_parameters(&tracking_area_update_accept->extended_drx_parameters, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_TYPE: - size = ogs_nas_decode_header_compression_configuration_status(&tracking_area_update_accept->header_compression_configuration_status, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_tracking_area_update_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_tracking_area_update_reject_t *tracking_area_update_reject = &message->emm.tracking_area_update_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_REJECT\n"); - - size = ogs_nas_decode_emm_cause(&tracking_area_update_reject->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_reject->t3346_value, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_reject->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_TYPE: - size = ogs_nas_decode_extended_emm_cause(&tracking_area_update_reject->extended_emm_cause, pkbuf); - ogs_assert(size >= 0); - tracking_area_update_reject->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_extended_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_extended_service_request_t *extended_service_request = &message->emm.extended_service_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode EXTENDED_SERVICE_REQUEST\n"); - - size = ogs_nas_decode_service_type(&extended_service_request->service_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_mobile_identity(&extended_service_request->m_tmsi, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_TYPE: - size = ogs_nas_decode_csfb_response(&extended_service_request->csfb_response, pkbuf); - ogs_assert(size >= 0); - extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_PRESENT; - decoded += size; - break; - case OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE: - size = ogs_nas_decode_eps_bearer_context_status(&extended_service_request->eps_bearer_context_status, pkbuf); - ogs_assert(size >= 0); - extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; - decoded += size; - break; - case OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&extended_service_request->device_properties, pkbuf); - ogs_assert(size >= 0); - extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_service_request_t *service_request = &message->emm.service_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode SERVICE_REQUEST\n"); - - size = ogs_nas_decode_ksi_and_sequence_number(&service_request->ksi_and_sequence_number, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_short_mac(&service_request->message_authentication_code, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_service_reject_t *service_reject = &message->emm.service_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode SERVICE_REJECT\n"); - - size = ogs_nas_decode_emm_cause(&service_reject->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_2(&service_reject->t3346_value, pkbuf); - ogs_assert(size >= 0); - service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_guti_reallocation_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_guti_reallocation_command_t *guti_reallocation_command = &message->emm.guti_reallocation_command; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode GUTI_REALLOCATION_COMMAND\n"); - - size = ogs_nas_decode_eps_mobile_identity(&guti_reallocation_command->guti, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_TYPE: - size = ogs_nas_decode_tracking_area_identity_list(&guti_reallocation_command->tai_list, pkbuf); - ogs_assert(size >= 0); - guti_reallocation_command->presencemask |= OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_authentication_request_t *authentication_request = &message->emm.authentication_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode AUTHENTICATION_REQUEST\n"); - - size = ogs_nas_decode_key_set_identifier(&authentication_request->nas_key_set_identifierasme, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_authentication_parameter_rand(&authentication_request->authentication_parameter_rand, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_authentication_parameter_autn(&authentication_request->authentication_parameter_autn, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_authentication_response_t *authentication_response = &message->emm.authentication_response; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode AUTHENTICATION_RESPONSE\n"); - - size = ogs_nas_decode_authentication_response_parameter(&authentication_response->authentication_response_parameter, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_identity_request_t *identity_request = &message->emm.identity_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode IDENTITY_REQUEST\n"); - - size = ogs_nas_decode_identity_type_2(&identity_request->identity_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_identity_response_t *identity_response = &message->emm.identity_response; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode IDENTITY_RESPONSE\n"); - - size = ogs_nas_decode_mobile_identity(&identity_response->mobile_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_authentication_failure_t *authentication_failure = &message->emm.authentication_failure; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode AUTHENTICATION_FAILURE\n"); - - size = ogs_nas_decode_emm_cause(&authentication_failure->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE: - size = ogs_nas_decode_authentication_failure_parameter(&authentication_failure->authentication_failure_parameter, pkbuf); - ogs_assert(size >= 0); - authentication_failure->presencemask |= OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_security_mode_command_t *security_mode_command = &message->emm.security_mode_command; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode SECURITY_MODE_COMMAND\n"); - - size = ogs_nas_decode_security_algorithms(&security_mode_command->selected_nas_security_algorithms, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_key_set_identifier(&security_mode_command->nas_key_set_identifier, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_ue_security_capability(&security_mode_command->replayed_ue_security_capabilities, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE: - size = ogs_nas_decode_imeisv_request(&security_mode_command->imeisv_request, pkbuf); - ogs_assert(size >= 0); - security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT; - decoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_TYPE: - size = ogs_nas_decode_nonce(&security_mode_command->replayed_nonceue, pkbuf); - ogs_assert(size >= 0); - security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_PRESENT; - decoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_TYPE: - size = ogs_nas_decode_nonce(&security_mode_command->noncemme, pkbuf); - ogs_assert(size >= 0); - security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_security_mode_complete_t *security_mode_complete = &message->emm.security_mode_complete; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode SECURITY_MODE_COMPLETE\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE: - size = ogs_nas_decode_mobile_identity(&security_mode_complete->imeisv, pkbuf); - ogs_assert(size >= 0); - security_mode_complete->presencemask |= OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_security_mode_reject_t *security_mode_reject = &message->emm.security_mode_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode SECURITY_MODE_REJECT\n"); - - size = ogs_nas_decode_emm_cause(&security_mode_reject->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_emm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_emm_status_t *emm_status = &message->emm.emm_status; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode EMM_STATUS\n"); - - size = ogs_nas_decode_emm_cause(&emm_status->emm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_emm_information(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_emm_information_t *emm_information = &message->emm.emm_information; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode EMM_INFORMATION\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_TYPE: - size = ogs_nas_decode_network_name(&emm_information->full_name_for_network, pkbuf); - ogs_assert(size >= 0); - emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT; - decoded += size; - break; - case OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_TYPE: - size = ogs_nas_decode_network_name(&emm_information->short_name_for_network, pkbuf); - ogs_assert(size >= 0); - emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT; - decoded += size; - break; - case OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_TYPE: - size = ogs_nas_decode_time_zone(&emm_information->local_time_zone, pkbuf); - ogs_assert(size >= 0); - emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_PRESENT; - decoded += size; - break; - case OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE: - size = ogs_nas_decode_time_zone_and_time(&emm_information->universal_time_and_local_time_zone, pkbuf); - ogs_assert(size >= 0); - emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT; - decoded += size; - break; - case OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_TYPE: - size = ogs_nas_decode_daylight_saving_time(&emm_information->network_daylight_saving_time, pkbuf); - ogs_assert(size >= 0); - emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_downlink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_downlink_nas_transport_t *downlink_nas_transport = &message->emm.downlink_nas_transport; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DOWNLINK_NAS_TRANSPORT\n"); - - size = ogs_nas_decode_message_container(&downlink_nas_transport->nas_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_uplink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_uplink_nas_transport_t *uplink_nas_transport = &message->emm.uplink_nas_transport; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode UPLINK_NAS_TRANSPORT\n"); - - size = ogs_nas_decode_message_container(&uplink_nas_transport->nas_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_decode_cs_service_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_cs_service_notification_t *cs_service_notification = &message->emm.cs_service_notification; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode CS_SERVICE_NOTIFICATION\n"); - - size = ogs_nas_decode_paging_identity(&cs_service_notification->paging_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_TYPE: - size = ogs_nas_decode_cli(&cs_service_notification->cli, pkbuf); - ogs_assert(size >= 0); - cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_PRESENT; - decoded += size; - break; - case OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_TYPE: - size = ogs_nas_decode_ss_code(&cs_service_notification->ss_code, pkbuf); - ogs_assert(size >= 0); - cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_PRESENT; - decoded += size; - break; - case OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_TYPE: - size = ogs_nas_decode_lcs_indicator(&cs_service_notification->lcs_indicator, pkbuf); - ogs_assert(size >= 0); - cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_PRESENT; - decoded += size; - break; - case OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_TYPE: - size = ogs_nas_decode_lcs_client_identity(&cs_service_notification->lcs_client_identity, pkbuf); - ogs_assert(size >= 0); - cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_uplink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_uplink_generic_nas_transport_t *uplink_generic_nas_transport = &message->emm.uplink_generic_nas_transport; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode UPLINK_GENERIC_NAS_TRANSPORT\n"); - - size = ogs_nas_decode_generic_message_container_type(&uplink_generic_nas_transport->generic_message_container_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_generic_message_container(&uplink_generic_nas_transport->generic_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: - size = ogs_nas_decode_additional_information(&uplink_generic_nas_transport->additional_information, pkbuf); - ogs_assert(size >= 0); - uplink_generic_nas_transport->presencemask |= OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_downlink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_downlink_generic_nas_transport_t *downlink_generic_nas_transport = &message->emm.downlink_generic_nas_transport; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DOWNLINK_GENERIC_NAS_TRANSPORT\n"); - - size = ogs_nas_decode_generic_message_container_type(&downlink_generic_nas_transport->generic_message_container_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_generic_message_container(&downlink_generic_nas_transport->generic_message_container, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: - size = ogs_nas_decode_additional_information(&downlink_generic_nas_transport->additional_information, pkbuf); - ogs_assert(size >= 0); - downlink_generic_nas_transport->presencemask |= OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_default_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_default_eps_bearer_context_request_t *activate_default_eps_bearer_context_request = &message->esm.activate_default_eps_bearer_context_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST\n"); - - size = ogs_nas_decode_eps_quality_of_service(&activate_default_eps_bearer_context_request->eps_qos, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_access_point_name(&activate_default_eps_bearer_context_request->access_point_name, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_pdn_address(&activate_default_eps_bearer_context_request->pdn_address, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE: - size = ogs_nas_decode_transaction_identifier(&activate_default_eps_bearer_context_request->transaction_identifier, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE: - size = ogs_nas_decode_quality_of_service(&activate_default_eps_bearer_context_request->negotiated_qos, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: - size = ogs_nas_decode_llc_service_access_point_identifier(&activate_default_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: - size = ogs_nas_decode_radio_priority(&activate_default_eps_bearer_context_request->radio_priority, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: - size = ogs_nas_decode_packet_flow_identifier(&activate_default_eps_bearer_context_request->packet_flow_identifier, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE: - size = ogs_nas_decode_apn_aggregate_maximum_bit_rate(&activate_default_eps_bearer_context_request->apn_ambr, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_TYPE: - size = ogs_nas_decode_esm_cause(&activate_default_eps_bearer_context_request->esm_cause, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_TYPE: - size = ogs_nas_decode_connectivity_type(&activate_default_eps_bearer_context_request->connectivity_type, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: - size = ogs_nas_decode_wlan_offload_acceptability(&activate_default_eps_bearer_context_request->wlan_offload_indication, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&activate_default_eps_bearer_context_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: - size = ogs_nas_decode_header_compression_configuration(&activate_default_eps_bearer_context_request->header_compression_configuration, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_TYPE: - size = ogs_nas_decode_control_plane_only_indication(&activate_default_eps_bearer_context_request->control_plane_only_indication, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_TYPE: - size = ogs_nas_decode_serving_plmn_rate_control(&activate_default_eps_bearer_context_request->serving_plmn_rate_control, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_default_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_default_eps_bearer_context_accept_t *activate_default_eps_bearer_context_accept = &message->esm.activate_default_eps_bearer_context_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_accept->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_default_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_default_eps_bearer_context_reject_t *activate_default_eps_bearer_context_reject = &message->esm.activate_default_eps_bearer_context_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&activate_default_eps_bearer_context_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_default_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_dedicated_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_dedicated_eps_bearer_context_request_t *activate_dedicated_eps_bearer_context_request = &message->esm.activate_dedicated_eps_bearer_context_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST\n"); - - size = ogs_nas_decode_linked_eps_bearer_identity(&activate_dedicated_eps_bearer_context_request->linked_eps_bearer_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_eps_quality_of_service(&activate_dedicated_eps_bearer_context_request->eps_qos, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_traffic_flow_template(&activate_dedicated_eps_bearer_context_request->tft, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE: - size = ogs_nas_decode_transaction_identifier(&activate_dedicated_eps_bearer_context_request->transaction_identifier, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE: - size = ogs_nas_decode_quality_of_service(&activate_dedicated_eps_bearer_context_request->negotiated_qos, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: - size = ogs_nas_decode_llc_service_access_point_identifier(&activate_dedicated_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: - size = ogs_nas_decode_radio_priority(&activate_dedicated_eps_bearer_context_request->radio_priority, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: - size = ogs_nas_decode_packet_flow_identifier(&activate_dedicated_eps_bearer_context_request->packet_flow_identifier, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: - size = ogs_nas_decode_wlan_offload_acceptability(&activate_dedicated_eps_bearer_context_request->wlan_offload_indication, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_dedicated_eps_bearer_context_accept_t *activate_dedicated_eps_bearer_context_accept = &message->esm.activate_dedicated_eps_bearer_context_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_accept->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_accept->nbifom_container, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_activate_dedicated_eps_bearer_context_reject_t *activate_dedicated_eps_bearer_context_reject = &message->esm.activate_dedicated_eps_bearer_context_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&activate_dedicated_eps_bearer_context_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_reject->nbifom_container, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_modify_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_modify_eps_bearer_context_request_t *modify_eps_bearer_context_request = &message->esm.modify_eps_bearer_context_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_REQUEST\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_TYPE: - size = ogs_nas_decode_eps_quality_of_service(&modify_eps_bearer_context_request->new_eps_qos, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_TYPE: - size = ogs_nas_decode_traffic_flow_template(&modify_eps_bearer_context_request->tft, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_TYPE: - size = ogs_nas_decode_quality_of_service(&modify_eps_bearer_context_request->new_qos, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: - size = ogs_nas_decode_llc_service_access_point_identifier(&modify_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: - size = ogs_nas_decode_radio_priority(&modify_eps_bearer_context_request->radio_priority, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: - size = ogs_nas_decode_packet_flow_identifier(&modify_eps_bearer_context_request->packet_flow_identifier, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE: - size = ogs_nas_decode_apn_aggregate_maximum_bit_rate(&modify_eps_bearer_context_request->apn_ambr, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: - size = ogs_nas_decode_wlan_offload_acceptability(&modify_eps_bearer_context_request->wlan_offload_indication, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: - size = ogs_nas_decode_header_compression_configuration(&modify_eps_bearer_context_request->header_compression_configuration, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_modify_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_modify_eps_bearer_context_accept_t *modify_eps_bearer_context_accept = &message->esm.modify_eps_bearer_context_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_ACCEPT\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_accept->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_accept->nbifom_container, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_modify_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_modify_eps_bearer_context_reject_t *modify_eps_bearer_context_reject = &message->esm.modify_eps_bearer_context_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&modify_eps_bearer_context_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_reject->nbifom_container, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_deactivate_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_deactivate_eps_bearer_context_request_t *deactivate_eps_bearer_context_request = &message->esm.deactivate_eps_bearer_context_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST\n"); - - size = ogs_nas_decode_esm_cause(&deactivate_eps_bearer_context_request->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&deactivate_eps_bearer_context_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&deactivate_eps_bearer_context_request->t3396_value, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: - size = ogs_nas_decode_wlan_offload_acceptability(&deactivate_eps_bearer_context_request->wlan_offload_indication, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&deactivate_eps_bearer_context_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&deactivate_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_deactivate_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_deactivate_eps_bearer_context_accept_t *deactivate_eps_bearer_context_accept = &message->esm.deactivate_eps_bearer_context_accept; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&deactivate_eps_bearer_context_accept->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_accept->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&deactivate_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - deactivate_eps_bearer_context_accept->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_pdn_connectivity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_pdn_connectivity_request_t *pdn_connectivity_request = &message->esm.pdn_connectivity_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode PDN_CONNECTIVITY_REQUEST\n"); - - size = ogs_nas_decode_request_type(&pdn_connectivity_request->request_type, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_TYPE: - size = ogs_nas_decode_esm_information_transfer_flag(&pdn_connectivity_request->esm_information_transfer_flag, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_TYPE: - size = ogs_nas_decode_access_point_name(&pdn_connectivity_request->access_point_name, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&pdn_connectivity_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&pdn_connectivity_request->device_properties, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&pdn_connectivity_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: - size = ogs_nas_decode_header_compression_configuration(&pdn_connectivity_request->header_compression_configuration, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_connectivity_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_pdn_connectivity_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_pdn_connectivity_reject_t *pdn_connectivity_reject = &message->esm.pdn_connectivity_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode PDN_CONNECTIVITY_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&pdn_connectivity_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&pdn_connectivity_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&pdn_connectivity_reject->back_off_timer_value, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_TYPE: - size = ogs_nas_decode_re_attempt_indicator(&pdn_connectivity_reject->re_attempt_indicator, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&pdn_connectivity_reject->nbifom_container, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_connectivity_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_pdn_disconnect_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_pdn_disconnect_request_t *pdn_disconnect_request = &message->esm.pdn_disconnect_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode PDN_DISCONNECT_REQUEST\n"); - - size = ogs_nas_decode_linked_eps_bearer_identity(&pdn_disconnect_request->linked_eps_bearer_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&pdn_disconnect_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_disconnect_request->presencemask |= OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_disconnect_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_disconnect_request->presencemask |= OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_pdn_disconnect_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_pdn_disconnect_reject_t *pdn_disconnect_reject = &message->esm.pdn_disconnect_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode PDN_DISCONNECT_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&pdn_disconnect_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&pdn_disconnect_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_disconnect_reject->presencemask |= OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_disconnect_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - pdn_disconnect_reject->presencemask |= OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_bearer_resource_allocation_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_bearer_resource_allocation_request_t *bearer_resource_allocation_request = &message->esm.bearer_resource_allocation_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode BEARER_RESOURCE_ALLOCATION_REQUEST\n"); - - size = ogs_nas_decode_linked_eps_bearer_identity(&bearer_resource_allocation_request->linked_eps_bearer_identity, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_traffic_flow_aggregate_description(&bearer_resource_allocation_request->traffic_flow_aggregate, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_eps_quality_of_service(&bearer_resource_allocation_request->required_traffic_flow_qos, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_allocation_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&bearer_resource_allocation_request->device_properties, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&bearer_resource_allocation_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_allocation_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_bearer_resource_allocation_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_bearer_resource_allocation_reject_t *bearer_resource_allocation_reject = &message->esm.bearer_resource_allocation_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode BEARER_RESOURCE_ALLOCATION_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&bearer_resource_allocation_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_allocation_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&bearer_resource_allocation_reject->back_off_timer_value, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE: - size = ogs_nas_decode_re_attempt_indicator(&bearer_resource_allocation_reject->re_attempt_indicator, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&bearer_resource_allocation_reject->nbifom_container, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_allocation_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_bearer_resource_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_bearer_resource_modification_request_t *bearer_resource_modification_request = &message->esm.bearer_resource_modification_request; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode BEARER_RESOURCE_MODIFICATION_REQUEST\n"); - - size = ogs_nas_decode_linked_eps_bearer_identity(&bearer_resource_modification_request->eps_bearer_identity_for_packet_filter, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - size = ogs_nas_decode_traffic_flow_aggregate_description(&bearer_resource_modification_request->traffic_flow_aggregate, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_TYPE: - size = ogs_nas_decode_eps_quality_of_service(&bearer_resource_modification_request->required_traffic_flow_qos, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_TYPE: - size = ogs_nas_decode_esm_cause(&bearer_resource_modification_request->esm_cause, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_modification_request->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_TYPE: - size = ogs_nas_decode_device_properties(&bearer_resource_modification_request->device_properties, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&bearer_resource_modification_request->nbifom_container, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: - size = ogs_nas_decode_header_compression_configuration(&bearer_resource_modification_request->header_compression_configuration, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_modification_request->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_bearer_resource_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_bearer_resource_modification_reject_t *bearer_resource_modification_reject = &message->esm.bearer_resource_modification_reject; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode BEARER_RESOURCE_MODIFICATION_REJECT\n"); - - size = ogs_nas_decode_esm_cause(&bearer_resource_modification_reject->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_modification_reject->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE: - size = ogs_nas_decode_gprs_timer_3(&bearer_resource_modification_reject->back_off_timer_value, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE: - size = ogs_nas_decode_re_attempt_indicator(&bearer_resource_modification_reject->re_attempt_indicator, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_TYPE: - size = ogs_nas_decode_nbifom_container(&bearer_resource_modification_reject->nbifom_container, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_PRESENT; - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_modification_reject->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_esm_information_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_esm_information_response_t *esm_information_response = &message->esm.esm_information_response; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ESM_INFORMATION_RESPONSE\n"); - - while(pkbuf->len > 0) - { - uint8_t *buffer = pkbuf->data; - uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); - - size = sizeof(uint8_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - decoded += size; - - switch(type) - { - case OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_TYPE: - size = ogs_nas_decode_access_point_name(&esm_information_response->access_point_name, pkbuf); - ogs_assert(size >= 0); - esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT; - decoded += size; - break; - case OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_protocol_configuration_options(&esm_information_response->protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - case OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: - size = ogs_nas_decode_extended_protocol_configuration_options(&esm_information_response->extended_protocol_configuration_options, pkbuf); - ogs_assert(size >= 0); - esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; - decoded += size; - break; - default: - ogs_warn("Unknown type(0x%x) or not implemented\n", type); - break; - } - } - - return decoded; -} - -int ogs_nas_decode_esm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - ogs_nas_esm_status_t *esm_status = &message->esm.esm_status; - int decoded = 0; - int size = 0; - - ogs_trace("[NAS] Decode ESM_STATUS\n"); - - size = ogs_nas_decode_esm_cause(&esm_status->esm_cause, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - return decoded; -} - -int ogs_nas_emm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - int size = 0; - uint16_t decoded = 0; - - ogs_assert(pkbuf); - ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_message_t)); - - size = sizeof(ogs_nas_emm_header_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - memcpy(&message->emm.h, pkbuf->data - size, size); - decoded += size; - - if (message->emm.h.security_header_type >= - OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) - { - ogs_assert(ogs_pkbuf_push(pkbuf, 1)); - decoded -= 1; - size = ogs_nas_decode_service_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - - goto out; - } - - switch(message->emm.h.message_type) - { - case OGS_NAS_ATTACH_REQUEST: - size = ogs_nas_decode_attach_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT: - size = ogs_nas_decode_attach_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ATTACH_COMPLETE: - size = ogs_nas_decode_attach_complete(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ATTACH_REJECT: - size = ogs_nas_decode_attach_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DETACH_REQUEST: - size = ogs_nas_decode_detach_request_from_ue(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DETACH_ACCEPT: - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST: - size = ogs_nas_decode_tracking_area_update_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT: - size = ogs_nas_decode_tracking_area_update_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_COMPLETE: - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REJECT: - size = ogs_nas_decode_tracking_area_update_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_EXTENDED_SERVICE_REQUEST: - size = ogs_nas_decode_extended_service_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_SERVICE_REJECT: - size = ogs_nas_decode_service_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_GUTI_REALLOCATION_COMMAND: - size = ogs_nas_decode_guti_reallocation_command(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_GUTI_REALLOCATION_COMPLETE: - break; - case OGS_NAS_AUTHENTICATION_REQUEST: - size = ogs_nas_decode_authentication_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_AUTHENTICATION_RESPONSE: - size = ogs_nas_decode_authentication_response(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_AUTHENTICATION_REJECT: - break; - case OGS_NAS_IDENTITY_REQUEST: - size = ogs_nas_decode_identity_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_IDENTITY_RESPONSE: - size = ogs_nas_decode_identity_response(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_AUTHENTICATION_FAILURE: - size = ogs_nas_decode_authentication_failure(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMMAND: - size = ogs_nas_decode_security_mode_command(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMPLETE: - size = ogs_nas_decode_security_mode_complete(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_SECURITY_MODE_REJECT: - size = ogs_nas_decode_security_mode_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_EMM_STATUS: - size = ogs_nas_decode_emm_status(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_EMM_INFORMATION: - size = ogs_nas_decode_emm_information(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DOWNLINK_NAS_TRANSPORT: - size = ogs_nas_decode_downlink_nas_transport(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_UPLINK_NAS_TRANSPORT: - size = ogs_nas_decode_uplink_nas_transport(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_CS_SERVICE_NOTIFICATION: - size = ogs_nas_decode_cs_service_notification(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT: - size = ogs_nas_decode_uplink_generic_nas_transport(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT: - size = ogs_nas_decode_downlink_generic_nas_transport(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->emm.h.message_type); - break; - } - -out: - ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); - - return OGS_OK; -} -int ogs_nas_esm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) -{ - int size = 0; - uint16_t decoded = 0; - - ogs_assert(pkbuf); - ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_message_t)); - - size = sizeof(ogs_nas_esm_header_t); - ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - memcpy(&message->esm.h, pkbuf->data - size, size); - decoded += size; - - switch(message->esm.h.message_type) - { - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_decode_activate_default_eps_bearer_context_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_decode_activate_default_eps_bearer_context_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_decode_activate_default_eps_bearer_context_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_decode_activate_dedicated_eps_bearer_context_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_decode_modify_eps_bearer_context_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_decode_modify_eps_bearer_context_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_decode_modify_eps_bearer_context_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_decode_deactivate_eps_bearer_context_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_decode_deactivate_eps_bearer_context_accept(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST: - size = ogs_nas_decode_pdn_connectivity_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT: - size = ogs_nas_decode_pdn_connectivity_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REQUEST: - size = ogs_nas_decode_pdn_disconnect_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REJECT: - size = ogs_nas_decode_pdn_disconnect_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST: - size = ogs_nas_decode_bearer_resource_allocation_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT: - size = ogs_nas_decode_bearer_resource_allocation_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST: - size = ogs_nas_decode_bearer_resource_modification_request(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT: - size = ogs_nas_decode_bearer_resource_modification_reject(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ESM_INFORMATION_REQUEST: - break; - case OGS_NAS_ESM_INFORMATION_RESPONSE: - size = ogs_nas_decode_esm_information_response(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - case OGS_NAS_ESM_STATUS: - size = ogs_nas_decode_esm_status(message, pkbuf); - ogs_assert(size >= 0); - decoded += size; - break; - default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->esm.h.message_type); - break; - } - - ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); - - return OGS_OK; -} - diff --git a/lib/nas/eps/decoder.c b/lib/nas/eps/decoder.c new file mode 100644 index 000000000..2b36eb125 --- /dev/null +++ b/lib/nas/eps/decoder.c @@ -0,0 +1,2953 @@ +/* + * The MIT License + * + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* + * 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: 2020-05-21 20:07:15.951142 by acetcom + * from 24301-d80.docx + ******************************************************************************/ + +#include "ogs-nas-eps.h" + +int ogs_nas_decode_attach_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_attach_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_attach_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_attach_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_detach_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_detach_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_tracking_area_update_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_tracking_area_update_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_tracking_area_update_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_extended_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_guti_reallocation_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_emm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_emm_information(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_downlink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_uplink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_cs_service_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_uplink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_downlink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_default_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_default_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_default_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_dedicated_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_modify_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_modify_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_modify_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_deactivate_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_deactivate_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdn_connectivity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdn_connectivity_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdn_disconnect_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_pdn_disconnect_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_bearer_resource_allocation_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_bearer_resource_allocation_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_bearer_resource_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_bearer_resource_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_esm_information_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_esm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf); +int ogs_nas_decode_attach_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_attach_request_t *attach_request = &message->emm.attach_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ATTACH_REQUEST\n"); + + size = ogs_nas_decode_eps_attach_type(&attach_request->eps_attach_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eps_mobile_identity(&attach_request->eps_mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_ue_network_capability(&attach_request->ue_network_capability, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_esm_message_container(&attach_request->esm_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE: + size = ogs_nas_decode_p_tmsi_signature(&attach_request->old_p_tmsi_signature, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_TYPE: + size = ogs_nas_decode_eps_mobile_identity(&attach_request->additional_guti, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE: + size = ogs_nas_decode_tracking_area_identity(&attach_request->last_visited_registered_tai, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_TYPE: + size = ogs_nas_decode_drx_parameter(&attach_request->drx_parameter, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_TYPE: + size = ogs_nas_decode_ms_network_capability(&attach_request->ms_network_capability, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE: + size = ogs_nas_decode_location_area_identification(&attach_request->old_location_area_identification, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_TYPE: + size = ogs_nas_decode_tmsi_status(&attach_request->tmsi_status, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE: + size = ogs_nas_decode_mobile_station_classmark_2(&attach_request->mobile_station_classmark_2, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE: + size = ogs_nas_decode_mobile_station_classmark_3(&attach_request->mobile_station_classmark_3, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_TYPE: + size = ogs_nas_decode_supported_codec_list(&attach_request->supported_codecs, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE: + size = ogs_nas_decode_additional_update_type(&attach_request->additional_update_type, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE: + size = ogs_nas_decode_voice_domain_preference_and_ue_usage_setting(&attach_request->voice_domain_preference_and_ue_usage_setting, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&attach_request->device_properties, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_TYPE: + size = ogs_nas_decode_guti_type(&attach_request->old_guti_type, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_ms_network_feature_support(&attach_request->ms_network_feature_support, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE: + size = ogs_nas_decode_network_resource_identifier_container(&attach_request->tmsi_based_nri_container, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&attach_request->t3324_value, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&attach_request->t3412_extended_value, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(&attach_request->extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + attach_request->presencemask |= OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_attach_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_attach_accept_t *attach_accept = &message->emm.attach_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ATTACH_ACCEPT\n"); + + size = ogs_nas_decode_eps_attach_result(&attach_accept->eps_attach_result, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_gprs_timer(&attach_accept->t3412_value, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_tracking_area_identity_list(&attach_accept->tai_list, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_esm_message_container(&attach_accept->esm_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ATTACH_ACCEPT_GUTI_TYPE: + size = ogs_nas_decode_eps_mobile_identity(&attach_accept->guti, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE: + size = ogs_nas_decode_location_area_identification(&attach_accept->location_area_identification, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_TYPE: + size = ogs_nas_decode_mobile_identity(&attach_accept->ms_identity, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_TYPE: + size = ogs_nas_decode_emm_cause(&attach_accept->emm_cause, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&attach_accept->t3402_value, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&attach_accept->t3423_value, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_TYPE: + size = ogs_nas_decode_plmn_list(&attach_accept->equivalent_plmns, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE: + size = ogs_nas_decode_emergency_number_list(&attach_accept->emergency_number_list, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_eps_network_feature_support(&attach_accept->eps_network_feature_support, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE: + size = ogs_nas_decode_additional_update_result(&attach_accept->additional_update_result, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&attach_accept->t3412_extended_value, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&attach_accept->t3324_value, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(&attach_accept->extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_attach_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_attach_complete_t *attach_complete = &message->emm.attach_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ATTACH_COMPLETE\n"); + + size = ogs_nas_decode_esm_message_container(&attach_complete->esm_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_attach_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_attach_reject_t *attach_reject = &message->emm.attach_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ATTACH_REJECT\n"); + + size = ogs_nas_decode_emm_cause(&attach_reject->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_TYPE: + size = ogs_nas_decode_esm_message_container(&attach_reject->esm_message_container, pkbuf); + ogs_assert(size >= 0); + attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REJECT_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&attach_reject->t3346_value, pkbuf); + ogs_assert(size >= 0); + attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_T3346_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REJECT_T3402_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&attach_reject->t3402_value, pkbuf); + ogs_assert(size >= 0); + attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_T3402_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_TYPE: + size = ogs_nas_decode_extended_emm_cause(&attach_reject->extended_emm_cause, pkbuf); + ogs_assert(size >= 0); + attach_reject->presencemask |= OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_detach_request_from_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_detach_request_from_ue_t *detach_request_from_ue = &message->emm.detach_request_from_ue; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DETACH_REQUEST\n"); + + size = ogs_nas_decode_detach_type(&detach_request_from_ue->detach_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eps_mobile_identity(&detach_request_from_ue->eps_mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_detach_request_to_ue(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_detach_request_to_ue_t *detach_request_to_ue = &message->emm.detach_request_to_ue; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DETACH_REQUEST\n"); + + size = ogs_nas_decode_detach_type(&detach_request_to_ue->detach_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_DETACH_REQUEST_EMM_CAUSE_TYPE: + size = ogs_nas_decode_emm_cause(&detach_request_to_ue->emm_cause, pkbuf); + ogs_assert(size >= 0); + detach_request_to_ue->presencemask |= OGS_NAS_DETACH_REQUEST_EMM_CAUSE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_tracking_area_update_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_tracking_area_update_request_t *tracking_area_update_request = &message->emm.tracking_area_update_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_REQUEST\n"); + + size = ogs_nas_decode_eps_update_type(&tracking_area_update_request->eps_update_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_request->old_guti, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE: + size = ogs_nas_decode_key_set_identifier(&tracking_area_update_request->non_current_native_nas_key_set_identifier, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_TYPE: + size = ogs_nas_decode_ciphering_key_sequence_number(&tracking_area_update_request->gprs_ciphering_key_sequence_number, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE: + size = ogs_nas_decode_p_tmsi_signature(&tracking_area_update_request->old_p_tmsi_signature, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_TYPE: + size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_request->additional_guti, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_TYPE: + size = ogs_nas_decode_nonce(&tracking_area_update_request->nonceue, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_TYPE: + size = ogs_nas_decode_ue_network_capability(&tracking_area_update_request->ue_network_capability, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE: + size = ogs_nas_decode_tracking_area_identity(&tracking_area_update_request->last_visited_registered_tai, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_TYPE: + size = ogs_nas_decode_drx_parameter(&tracking_area_update_request->drx_parameter, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_TYPE: + size = ogs_nas_decode_ue_radio_capability_information_update_needed(&tracking_area_update_request->ue_radio_capability_information_update_needed, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE: + size = ogs_nas_decode_eps_bearer_context_status(&tracking_area_update_request->eps_bearer_context_status, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_TYPE: + size = ogs_nas_decode_ms_network_capability(&tracking_area_update_request->ms_network_capability, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE: + size = ogs_nas_decode_location_area_identification(&tracking_area_update_request->old_location_area_identification, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_TYPE: + size = ogs_nas_decode_tmsi_status(&tracking_area_update_request->tmsi_status, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE: + size = ogs_nas_decode_mobile_station_classmark_2(&tracking_area_update_request->mobile_station_classmark_2, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE: + size = ogs_nas_decode_mobile_station_classmark_3(&tracking_area_update_request->mobile_station_classmark_3, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_TYPE: + size = ogs_nas_decode_supported_codec_list(&tracking_area_update_request->supported_codecs, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE: + size = ogs_nas_decode_additional_update_type(&tracking_area_update_request->additional_update_type, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE: + size = ogs_nas_decode_voice_domain_preference_and_ue_usage_setting(&tracking_area_update_request->voice_domain_preference_and_ue_usage_setting, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_TYPE: + size = ogs_nas_decode_guti_type(&tracking_area_update_request->old_guti_type, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&tracking_area_update_request->device_properties, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_ms_network_feature_support(&tracking_area_update_request->ms_network_feature_support, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE: + size = ogs_nas_decode_network_resource_identifier_container(&tracking_area_update_request->tmsi_based_nri_container, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_request->t3324_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&tracking_area_update_request->t3412_extended_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(&tracking_area_update_request->extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_request->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_tracking_area_update_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_tracking_area_update_accept_t *tracking_area_update_accept = &message->emm.tracking_area_update_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_ACCEPT\n"); + + size = ogs_nas_decode_eps_update_result(&tracking_area_update_accept->eps_update_result, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3412_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_TYPE: + size = ogs_nas_decode_eps_mobile_identity(&tracking_area_update_accept->guti, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_TYPE: + size = ogs_nas_decode_tracking_area_identity_list(&tracking_area_update_accept->tai_list, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE: + size = ogs_nas_decode_eps_bearer_context_status(&tracking_area_update_accept->eps_bearer_context_status, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE: + size = ogs_nas_decode_location_area_identification(&tracking_area_update_accept->location_area_identification, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_TYPE: + size = ogs_nas_decode_mobile_identity(&tracking_area_update_accept->ms_identity, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_TYPE: + size = ogs_nas_decode_emm_cause(&tracking_area_update_accept->emm_cause, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3402_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer(&tracking_area_update_accept->t3423_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_TYPE: + size = ogs_nas_decode_plmn_list(&tracking_area_update_accept->equivalent_plmns, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE: + size = ogs_nas_decode_emergency_number_list(&tracking_area_update_accept->emergency_number_list, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE: + size = ogs_nas_decode_eps_network_feature_support(&tracking_area_update_accept->eps_network_feature_support, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE: + size = ogs_nas_decode_additional_update_result(&tracking_area_update_accept->additional_update_result, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&tracking_area_update_accept->t3412_extended_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_accept->t3324_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE: + size = ogs_nas_decode_extended_drx_parameters(&tracking_area_update_accept->extended_drx_parameters, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_TYPE: + size = ogs_nas_decode_header_compression_configuration_status(&tracking_area_update_accept->header_compression_configuration_status, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_accept->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_tracking_area_update_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_tracking_area_update_reject_t *tracking_area_update_reject = &message->emm.tracking_area_update_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode TRACKING_AREA_UPDATE_REJECT\n"); + + size = ogs_nas_decode_emm_cause(&tracking_area_update_reject->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&tracking_area_update_reject->t3346_value, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_reject->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_TYPE: + size = ogs_nas_decode_extended_emm_cause(&tracking_area_update_reject->extended_emm_cause, pkbuf); + ogs_assert(size >= 0); + tracking_area_update_reject->presencemask |= OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_extended_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_extended_service_request_t *extended_service_request = &message->emm.extended_service_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode EXTENDED_SERVICE_REQUEST\n"); + + size = ogs_nas_decode_service_type(&extended_service_request->service_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_mobile_identity(&extended_service_request->m_tmsi, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_TYPE: + size = ogs_nas_decode_csfb_response(&extended_service_request->csfb_response, pkbuf); + ogs_assert(size >= 0); + extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_PRESENT; + decoded += size; + break; + case OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE: + size = ogs_nas_decode_eps_bearer_context_status(&extended_service_request->eps_bearer_context_status, pkbuf); + ogs_assert(size >= 0); + extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; + decoded += size; + break; + case OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&extended_service_request->device_properties, pkbuf); + ogs_assert(size >= 0); + extended_service_request->presencemask |= OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_service_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_service_request_t *service_request = &message->emm.service_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SERVICE_REQUEST\n"); + + size = ogs_nas_decode_ksi_and_sequence_number(&service_request->ksi_and_sequence_number, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_short_mac(&service_request->message_authentication_code, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_service_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_service_reject_t *service_reject = &message->emm.service_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SERVICE_REJECT\n"); + + size = ogs_nas_decode_emm_cause(&service_reject->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_2(&service_reject->t3346_value, pkbuf); + ogs_assert(size >= 0); + service_reject->presencemask |= OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_guti_reallocation_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_guti_reallocation_command_t *guti_reallocation_command = &message->emm.guti_reallocation_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode GUTI_REALLOCATION_COMMAND\n"); + + size = ogs_nas_decode_eps_mobile_identity(&guti_reallocation_command->guti, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_TYPE: + size = ogs_nas_decode_tracking_area_identity_list(&guti_reallocation_command->tai_list, pkbuf); + ogs_assert(size >= 0); + guti_reallocation_command->presencemask |= OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_authentication_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_request_t *authentication_request = &message->emm.authentication_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_REQUEST\n"); + + size = ogs_nas_decode_key_set_identifier(&authentication_request->nas_key_set_identifierasme, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_authentication_parameter_rand(&authentication_request->authentication_parameter_rand, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_authentication_parameter_autn(&authentication_request->authentication_parameter_autn, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_authentication_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_response_t *authentication_response = &message->emm.authentication_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_RESPONSE\n"); + + size = ogs_nas_decode_authentication_response_parameter(&authentication_response->authentication_response_parameter, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_identity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_identity_request_t *identity_request = &message->emm.identity_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode IDENTITY_REQUEST\n"); + + size = ogs_nas_decode_identity_type_2(&identity_request->identity_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_identity_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_identity_response_t *identity_response = &message->emm.identity_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode IDENTITY_RESPONSE\n"); + + size = ogs_nas_decode_mobile_identity(&identity_response->mobile_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_authentication_failure(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_authentication_failure_t *authentication_failure = &message->emm.authentication_failure; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode AUTHENTICATION_FAILURE\n"); + + size = ogs_nas_decode_emm_cause(&authentication_failure->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE: + size = ogs_nas_decode_authentication_failure_parameter(&authentication_failure->authentication_failure_parameter, pkbuf); + ogs_assert(size >= 0); + authentication_failure->presencemask |= OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_security_mode_command(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_command_t *security_mode_command = &message->emm.security_mode_command; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_COMMAND\n"); + + size = ogs_nas_decode_security_algorithms(&security_mode_command->selected_nas_security_algorithms, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_key_set_identifier(&security_mode_command->nas_key_set_identifier, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_ue_security_capability(&security_mode_command->replayed_ue_security_capabilities, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE: + size = ogs_nas_decode_imeisv_request(&security_mode_command->imeisv_request, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_TYPE: + size = ogs_nas_decode_nonce(&security_mode_command->replayed_nonceue, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_PRESENT; + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_TYPE: + size = ogs_nas_decode_nonce(&security_mode_command->noncemme, pkbuf); + ogs_assert(size >= 0); + security_mode_command->presencemask |= OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_security_mode_complete(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_complete_t *security_mode_complete = &message->emm.security_mode_complete; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_COMPLETE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE: + size = ogs_nas_decode_mobile_identity(&security_mode_complete->imeisv, pkbuf); + ogs_assert(size >= 0); + security_mode_complete->presencemask |= OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_security_mode_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_security_mode_reject_t *security_mode_reject = &message->emm.security_mode_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode SECURITY_MODE_REJECT\n"); + + size = ogs_nas_decode_emm_cause(&security_mode_reject->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_emm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_emm_status_t *emm_status = &message->emm.emm_status; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode EMM_STATUS\n"); + + size = ogs_nas_decode_emm_cause(&emm_status->emm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_emm_information(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_emm_information_t *emm_information = &message->emm.emm_information; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode EMM_INFORMATION\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_TYPE: + size = ogs_nas_decode_network_name(&emm_information->full_name_for_network, pkbuf); + ogs_assert(size >= 0); + emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT; + decoded += size; + break; + case OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_TYPE: + size = ogs_nas_decode_network_name(&emm_information->short_name_for_network, pkbuf); + ogs_assert(size >= 0); + emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT; + decoded += size; + break; + case OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_TYPE: + size = ogs_nas_decode_time_zone(&emm_information->local_time_zone, pkbuf); + ogs_assert(size >= 0); + emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_PRESENT; + decoded += size; + break; + case OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE: + size = ogs_nas_decode_time_zone_and_time(&emm_information->universal_time_and_local_time_zone, pkbuf); + ogs_assert(size >= 0); + emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT; + decoded += size; + break; + case OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_TYPE: + size = ogs_nas_decode_daylight_saving_time(&emm_information->network_daylight_saving_time, pkbuf); + ogs_assert(size >= 0); + emm_information->presencemask |= OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_downlink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_downlink_nas_transport_t *downlink_nas_transport = &message->emm.downlink_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DOWNLINK_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_message_container(&downlink_nas_transport->nas_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_uplink_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_uplink_nas_transport_t *uplink_nas_transport = &message->emm.uplink_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode UPLINK_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_message_container(&uplink_nas_transport->nas_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_decode_cs_service_notification(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_cs_service_notification_t *cs_service_notification = &message->emm.cs_service_notification; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode CS_SERVICE_NOTIFICATION\n"); + + size = ogs_nas_decode_paging_identity(&cs_service_notification->paging_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_TYPE: + size = ogs_nas_decode_cli(&cs_service_notification->cli, pkbuf); + ogs_assert(size >= 0); + cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_PRESENT; + decoded += size; + break; + case OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_TYPE: + size = ogs_nas_decode_ss_code(&cs_service_notification->ss_code, pkbuf); + ogs_assert(size >= 0); + cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_PRESENT; + decoded += size; + break; + case OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_TYPE: + size = ogs_nas_decode_lcs_indicator(&cs_service_notification->lcs_indicator, pkbuf); + ogs_assert(size >= 0); + cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_TYPE: + size = ogs_nas_decode_lcs_client_identity(&cs_service_notification->lcs_client_identity, pkbuf); + ogs_assert(size >= 0); + cs_service_notification->presencemask |= OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_uplink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_uplink_generic_nas_transport_t *uplink_generic_nas_transport = &message->emm.uplink_generic_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode UPLINK_GENERIC_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_generic_message_container_type(&uplink_generic_nas_transport->generic_message_container_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_generic_message_container(&uplink_generic_nas_transport->generic_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&uplink_generic_nas_transport->additional_information, pkbuf); + ogs_assert(size >= 0); + uplink_generic_nas_transport->presencemask |= OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_downlink_generic_nas_transport(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_downlink_generic_nas_transport_t *downlink_generic_nas_transport = &message->emm.downlink_generic_nas_transport; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DOWNLINK_GENERIC_NAS_TRANSPORT\n"); + + size = ogs_nas_decode_generic_message_container_type(&downlink_generic_nas_transport->generic_message_container_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_generic_message_container(&downlink_generic_nas_transport->generic_message_container, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE: + size = ogs_nas_decode_additional_information(&downlink_generic_nas_transport->additional_information, pkbuf); + ogs_assert(size >= 0); + downlink_generic_nas_transport->presencemask |= OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_default_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_default_eps_bearer_context_request_t *activate_default_eps_bearer_context_request = &message->esm.activate_default_eps_bearer_context_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST\n"); + + size = ogs_nas_decode_eps_quality_of_service(&activate_default_eps_bearer_context_request->eps_qos, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_access_point_name(&activate_default_eps_bearer_context_request->access_point_name, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_pdn_address(&activate_default_eps_bearer_context_request->pdn_address, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE: + size = ogs_nas_decode_transaction_identifier(&activate_default_eps_bearer_context_request->transaction_identifier, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE: + size = ogs_nas_decode_quality_of_service(&activate_default_eps_bearer_context_request->negotiated_qos, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: + size = ogs_nas_decode_llc_service_access_point_identifier(&activate_default_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: + size = ogs_nas_decode_radio_priority(&activate_default_eps_bearer_context_request->radio_priority, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: + size = ogs_nas_decode_packet_flow_identifier(&activate_default_eps_bearer_context_request->packet_flow_identifier, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE: + size = ogs_nas_decode_apn_aggregate_maximum_bit_rate(&activate_default_eps_bearer_context_request->apn_ambr, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_TYPE: + size = ogs_nas_decode_esm_cause(&activate_default_eps_bearer_context_request->esm_cause, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_TYPE: + size = ogs_nas_decode_connectivity_type(&activate_default_eps_bearer_context_request->connectivity_type, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: + size = ogs_nas_decode_wlan_offload_acceptability(&activate_default_eps_bearer_context_request->wlan_offload_indication, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&activate_default_eps_bearer_context_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&activate_default_eps_bearer_context_request->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_TYPE: + size = ogs_nas_decode_control_plane_only_indication(&activate_default_eps_bearer_context_request->control_plane_only_indication, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_TYPE: + size = ogs_nas_decode_serving_plmn_rate_control(&activate_default_eps_bearer_context_request->serving_plmn_rate_control, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_default_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_default_eps_bearer_context_accept_t *activate_default_eps_bearer_context_accept = &message->esm.activate_default_eps_bearer_context_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_accept->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_default_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_default_eps_bearer_context_reject_t *activate_default_eps_bearer_context_reject = &message->esm.activate_default_eps_bearer_context_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&activate_default_eps_bearer_context_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_default_eps_bearer_context_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_default_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_default_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_dedicated_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_dedicated_eps_bearer_context_request_t *activate_dedicated_eps_bearer_context_request = &message->esm.activate_dedicated_eps_bearer_context_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST\n"); + + size = ogs_nas_decode_linked_eps_bearer_identity(&activate_dedicated_eps_bearer_context_request->linked_eps_bearer_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eps_quality_of_service(&activate_dedicated_eps_bearer_context_request->eps_qos, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_traffic_flow_template(&activate_dedicated_eps_bearer_context_request->tft, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE: + size = ogs_nas_decode_transaction_identifier(&activate_dedicated_eps_bearer_context_request->transaction_identifier, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE: + size = ogs_nas_decode_quality_of_service(&activate_dedicated_eps_bearer_context_request->negotiated_qos, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: + size = ogs_nas_decode_llc_service_access_point_identifier(&activate_dedicated_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: + size = ogs_nas_decode_radio_priority(&activate_dedicated_eps_bearer_context_request->radio_priority, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: + size = ogs_nas_decode_packet_flow_identifier(&activate_dedicated_eps_bearer_context_request->packet_flow_identifier, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: + size = ogs_nas_decode_wlan_offload_acceptability(&activate_dedicated_eps_bearer_context_request->wlan_offload_indication, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_request->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_dedicated_eps_bearer_context_accept_t *activate_dedicated_eps_bearer_context_accept = &message->esm.activate_dedicated_eps_bearer_context_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_accept->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_accept->nbifom_container, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_accept->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_activate_dedicated_eps_bearer_context_reject_t *activate_dedicated_eps_bearer_context_reject = &message->esm.activate_dedicated_eps_bearer_context_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&activate_dedicated_eps_bearer_context_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&activate_dedicated_eps_bearer_context_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&activate_dedicated_eps_bearer_context_reject->nbifom_container, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&activate_dedicated_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + activate_dedicated_eps_bearer_context_reject->presencemask |= OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_modify_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_modify_eps_bearer_context_request_t *modify_eps_bearer_context_request = &message->esm.modify_eps_bearer_context_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_REQUEST\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_TYPE: + size = ogs_nas_decode_eps_quality_of_service(&modify_eps_bearer_context_request->new_eps_qos, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_TYPE: + size = ogs_nas_decode_traffic_flow_template(&modify_eps_bearer_context_request->tft, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_TYPE: + size = ogs_nas_decode_quality_of_service(&modify_eps_bearer_context_request->new_qos, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE: + size = ogs_nas_decode_llc_service_access_point_identifier(&modify_eps_bearer_context_request->negotiated_llc_sapi, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE: + size = ogs_nas_decode_radio_priority(&modify_eps_bearer_context_request->radio_priority, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE: + size = ogs_nas_decode_packet_flow_identifier(&modify_eps_bearer_context_request->packet_flow_identifier, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE: + size = ogs_nas_decode_apn_aggregate_maximum_bit_rate(&modify_eps_bearer_context_request->apn_ambr, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: + size = ogs_nas_decode_wlan_offload_acceptability(&modify_eps_bearer_context_request->wlan_offload_indication, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&modify_eps_bearer_context_request->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_request->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_modify_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_modify_eps_bearer_context_accept_t *modify_eps_bearer_context_accept = &message->esm.modify_eps_bearer_context_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_ACCEPT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_accept->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_accept->nbifom_container, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_accept->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_modify_eps_bearer_context_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_modify_eps_bearer_context_reject_t *modify_eps_bearer_context_reject = &message->esm.modify_eps_bearer_context_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode MODIFY_EPS_BEARER_CONTEXT_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&modify_eps_bearer_context_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&modify_eps_bearer_context_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&modify_eps_bearer_context_reject->nbifom_container, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&modify_eps_bearer_context_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + modify_eps_bearer_context_reject->presencemask |= OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_deactivate_eps_bearer_context_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_deactivate_eps_bearer_context_request_t *deactivate_eps_bearer_context_request = &message->esm.deactivate_eps_bearer_context_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST\n"); + + size = ogs_nas_decode_esm_cause(&deactivate_eps_bearer_context_request->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&deactivate_eps_bearer_context_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&deactivate_eps_bearer_context_request->t3396_value, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE: + size = ogs_nas_decode_wlan_offload_acceptability(&deactivate_eps_bearer_context_request->wlan_offload_indication, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT; + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&deactivate_eps_bearer_context_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&deactivate_eps_bearer_context_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_request->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_deactivate_eps_bearer_context_accept(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_deactivate_eps_bearer_context_accept_t *deactivate_eps_bearer_context_accept = &message->esm.deactivate_eps_bearer_context_accept; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&deactivate_eps_bearer_context_accept->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_accept->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&deactivate_eps_bearer_context_accept->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + deactivate_eps_bearer_context_accept->presencemask |= OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdn_connectivity_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdn_connectivity_request_t *pdn_connectivity_request = &message->esm.pdn_connectivity_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDN_CONNECTIVITY_REQUEST\n"); + + size = ogs_nas_decode_request_type(&pdn_connectivity_request->request_type, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_TYPE: + size = ogs_nas_decode_esm_information_transfer_flag(&pdn_connectivity_request->esm_information_transfer_flag, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_TYPE: + size = ogs_nas_decode_access_point_name(&pdn_connectivity_request->access_point_name, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&pdn_connectivity_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&pdn_connectivity_request->device_properties, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&pdn_connectivity_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&pdn_connectivity_request->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_connectivity_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_request->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdn_connectivity_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdn_connectivity_reject_t *pdn_connectivity_reject = &message->esm.pdn_connectivity_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDN_CONNECTIVITY_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&pdn_connectivity_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&pdn_connectivity_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&pdn_connectivity_reject->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_re_attempt_indicator(&pdn_connectivity_reject->re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&pdn_connectivity_reject->nbifom_container, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_connectivity_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_connectivity_reject->presencemask |= OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdn_disconnect_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdn_disconnect_request_t *pdn_disconnect_request = &message->esm.pdn_disconnect_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDN_DISCONNECT_REQUEST\n"); + + size = ogs_nas_decode_linked_eps_bearer_identity(&pdn_disconnect_request->linked_eps_bearer_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&pdn_disconnect_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_disconnect_request->presencemask |= OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_disconnect_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_disconnect_request->presencemask |= OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_pdn_disconnect_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_pdn_disconnect_reject_t *pdn_disconnect_reject = &message->esm.pdn_disconnect_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode PDN_DISCONNECT_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&pdn_disconnect_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&pdn_disconnect_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_disconnect_reject->presencemask |= OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&pdn_disconnect_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + pdn_disconnect_reject->presencemask |= OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_bearer_resource_allocation_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_bearer_resource_allocation_request_t *bearer_resource_allocation_request = &message->esm.bearer_resource_allocation_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode BEARER_RESOURCE_ALLOCATION_REQUEST\n"); + + size = ogs_nas_decode_linked_eps_bearer_identity(&bearer_resource_allocation_request->linked_eps_bearer_identity, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_traffic_flow_aggregate_description(&bearer_resource_allocation_request->traffic_flow_aggregate, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_eps_quality_of_service(&bearer_resource_allocation_request->required_traffic_flow_qos, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_allocation_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&bearer_resource_allocation_request->device_properties, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&bearer_resource_allocation_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_allocation_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_request->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_bearer_resource_allocation_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_bearer_resource_allocation_reject_t *bearer_resource_allocation_reject = &message->esm.bearer_resource_allocation_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode BEARER_RESOURCE_ALLOCATION_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&bearer_resource_allocation_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_allocation_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&bearer_resource_allocation_reject->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_re_attempt_indicator(&bearer_resource_allocation_reject->re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&bearer_resource_allocation_reject->nbifom_container, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_allocation_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_allocation_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_bearer_resource_modification_request(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_bearer_resource_modification_request_t *bearer_resource_modification_request = &message->esm.bearer_resource_modification_request; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode BEARER_RESOURCE_MODIFICATION_REQUEST\n"); + + size = ogs_nas_decode_linked_eps_bearer_identity(&bearer_resource_modification_request->eps_bearer_identity_for_packet_filter, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + size = ogs_nas_decode_traffic_flow_aggregate_description(&bearer_resource_modification_request->traffic_flow_aggregate, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_TYPE: + size = ogs_nas_decode_eps_quality_of_service(&bearer_resource_modification_request->required_traffic_flow_qos, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_TYPE: + size = ogs_nas_decode_esm_cause(&bearer_resource_modification_request->esm_cause, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_modification_request->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_TYPE: + size = ogs_nas_decode_device_properties(&bearer_resource_modification_request->device_properties, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&bearer_resource_modification_request->nbifom_container, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE: + size = ogs_nas_decode_header_compression_configuration(&bearer_resource_modification_request->header_compression_configuration, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_modification_request->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_request->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_bearer_resource_modification_reject(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_bearer_resource_modification_reject_t *bearer_resource_modification_reject = &message->esm.bearer_resource_modification_reject; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode BEARER_RESOURCE_MODIFICATION_REJECT\n"); + + size = ogs_nas_decode_esm_cause(&bearer_resource_modification_reject->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&bearer_resource_modification_reject->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE: + size = ogs_nas_decode_gprs_timer_3(&bearer_resource_modification_reject->back_off_timer_value, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE: + size = ogs_nas_decode_re_attempt_indicator(&bearer_resource_modification_reject->re_attempt_indicator, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_TYPE: + size = ogs_nas_decode_nbifom_container(&bearer_resource_modification_reject->nbifom_container, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_PRESENT; + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&bearer_resource_modification_reject->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + bearer_resource_modification_reject->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_esm_information_response(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_esm_information_response_t *esm_information_response = &message->esm.esm_information_response; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ESM_INFORMATION_RESPONSE\n"); + + while (pkbuf->len > 0) { + uint8_t *buffer = pkbuf->data; + uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); + + size = sizeof(uint8_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + decoded += size; + + switch (type) { + case OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_TYPE: + size = ogs_nas_decode_access_point_name(&esm_information_response->access_point_name, pkbuf); + ogs_assert(size >= 0); + esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT; + decoded += size; + break; + case OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_protocol_configuration_options(&esm_information_response->protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + case OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE: + size = ogs_nas_decode_extended_protocol_configuration_options(&esm_information_response->extended_protocol_configuration_options, pkbuf); + ogs_assert(size >= 0); + esm_information_response->presencemask |= OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + decoded += size; + break; + default: + ogs_warn("Unknown type(0x%x) or not implemented\n", type); + break; + } + } + + return decoded; +} + +int ogs_nas_decode_esm_status(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + ogs_nas_esm_status_t *esm_status = &message->esm.esm_status; + int decoded = 0; + int size = 0; + + ogs_trace("[NAS] Decode ESM_STATUS\n"); + + size = ogs_nas_decode_esm_cause(&esm_status->esm_cause, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + return decoded; +} + +int ogs_nas_emm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_emm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->emm.h, pkbuf->data - size, size); + decoded += size; + + if (message->emm.h.security_header_type >= + OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { + ogs_assert(ogs_pkbuf_push(pkbuf, 1)); + decoded -= 1; + size = ogs_nas_decode_service_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + + goto out; + } + + switch (message->emm.h.message_type) { + case OGS_NAS_ATTACH_REQUEST: + size = ogs_nas_decode_attach_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT: + size = ogs_nas_decode_attach_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ATTACH_COMPLETE: + size = ogs_nas_decode_attach_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ATTACH_REJECT: + size = ogs_nas_decode_attach_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DETACH_REQUEST: + size = ogs_nas_decode_detach_request_from_ue(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DETACH_ACCEPT: + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST: + size = ogs_nas_decode_tracking_area_update_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT: + size = ogs_nas_decode_tracking_area_update_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_COMPLETE: + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REJECT: + size = ogs_nas_decode_tracking_area_update_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_EXTENDED_SERVICE_REQUEST: + size = ogs_nas_decode_extended_service_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SERVICE_REJECT: + size = ogs_nas_decode_service_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_GUTI_REALLOCATION_COMMAND: + size = ogs_nas_decode_guti_reallocation_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_GUTI_REALLOCATION_COMPLETE: + break; + case OGS_NAS_AUTHENTICATION_REQUEST: + size = ogs_nas_decode_authentication_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESPONSE: + size = ogs_nas_decode_authentication_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_REJECT: + break; + case OGS_NAS_IDENTITY_REQUEST: + size = ogs_nas_decode_identity_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_IDENTITY_RESPONSE: + size = ogs_nas_decode_identity_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_AUTHENTICATION_FAILURE: + size = ogs_nas_decode_authentication_failure(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND: + size = ogs_nas_decode_security_mode_command(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE: + size = ogs_nas_decode_security_mode_complete(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_SECURITY_MODE_REJECT: + size = ogs_nas_decode_security_mode_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_EMM_STATUS: + size = ogs_nas_decode_emm_status(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_EMM_INFORMATION: + size = ogs_nas_decode_emm_information(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DOWNLINK_NAS_TRANSPORT: + size = ogs_nas_decode_downlink_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_UPLINK_NAS_TRANSPORT: + size = ogs_nas_decode_uplink_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_CS_SERVICE_NOTIFICATION: + size = ogs_nas_decode_cs_service_notification(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT: + size = ogs_nas_decode_uplink_generic_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT: + size = ogs_nas_decode_downlink_generic_nas_transport(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->emm.h.message_type); + break; + } + +out: + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} +int ogs_nas_esm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf) +{ + int size = 0; + uint16_t decoded = 0; + + ogs_assert(pkbuf); + ogs_assert(pkbuf->data); + ogs_assert(pkbuf->len); + + memset(message, 0, sizeof(ogs_nas_message_t)); + + size = sizeof(ogs_nas_esm_header_t); + ogs_assert(ogs_pkbuf_pull(pkbuf, size)); + memcpy(&message->esm.h, pkbuf->data - size, size); + decoded += size; + + switch (message->esm.h.message_type) { + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_decode_activate_default_eps_bearer_context_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_decode_activate_default_eps_bearer_context_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_decode_activate_default_eps_bearer_context_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_decode_activate_dedicated_eps_bearer_context_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_decode_activate_dedicated_eps_bearer_context_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_decode_activate_dedicated_eps_bearer_context_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_decode_modify_eps_bearer_context_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_decode_modify_eps_bearer_context_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_decode_modify_eps_bearer_context_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_decode_deactivate_eps_bearer_context_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_decode_deactivate_eps_bearer_context_accept(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST: + size = ogs_nas_decode_pdn_connectivity_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT: + size = ogs_nas_decode_pdn_connectivity_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REQUEST: + size = ogs_nas_decode_pdn_disconnect_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REJECT: + size = ogs_nas_decode_pdn_disconnect_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST: + size = ogs_nas_decode_bearer_resource_allocation_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT: + size = ogs_nas_decode_bearer_resource_allocation_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST: + size = ogs_nas_decode_bearer_resource_modification_request(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT: + size = ogs_nas_decode_bearer_resource_modification_reject(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ESM_INFORMATION_REQUEST: + break; + case OGS_NAS_ESM_INFORMATION_RESPONSE: + size = ogs_nas_decode_esm_information_response(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + case OGS_NAS_ESM_STATUS: + size = ogs_nas_decode_esm_status(message, pkbuf); + ogs_assert(size >= 0); + decoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->esm.h.message_type); + break; + } + + ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); + + return OGS_OK; +} + diff --git a/lib/nas/encoder.c b/lib/nas/eps/encoder.c similarity index 86% rename from lib/nas/encoder.c rename to lib/nas/eps/encoder.c index 0ef01f2ce..3c29fed24 100644 --- a/lib/nas/encoder.c +++ b/lib/nas/eps/encoder.c @@ -28,11 +28,11 @@ /******************************************************************************* * 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: 2020-04-24 08:50:31.653587 by acetcom + * Created on: 2020-05-21 20:07:15.961620 by acetcom * from 24301-d80.docx ******************************************************************************/ -#include "ogs-nas.h" +#include "ogs-nas-eps.h" int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message); @@ -107,8 +107,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message ogs_assert(size >= 0); encoded += size; - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -118,8 +117,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -129,8 +127,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -140,8 +137,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_DRX_PARAMETER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -151,8 +147,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -162,8 +157,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -173,8 +167,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_PRESENT) { attach_request->tmsi_status.type = (OGS_NAS_ATTACH_REQUEST_TMSI_STATUS_TYPE >> 4); size = ogs_nas_encode_tmsi_status(pkbuf, &attach_request->tmsi_status); @@ -182,8 +175,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE); ogs_assert(size >= 0); encoded += size; @@ -193,8 +185,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE); ogs_assert(size >= 0); encoded += size; @@ -204,8 +195,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_SUPPORTED_CODECS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -215,8 +205,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT) { attach_request->additional_update_type.type = (OGS_NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE >> 4); size = ogs_nas_encode_additional_update_type(pkbuf, &attach_request->additional_update_type); @@ -224,8 +213,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE); ogs_assert(size >= 0); encoded += size; @@ -235,8 +223,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_PRESENT) { attach_request->device_properties.type = (OGS_NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &attach_request->device_properties); @@ -244,8 +231,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_PRESENT) { attach_request->old_guti_type.type = (OGS_NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_TYPE >> 4); size = ogs_nas_encode_guti_type(pkbuf, &attach_request->old_guti_type); @@ -253,8 +239,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT) { attach_request->ms_network_feature_support.type = (OGS_NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE >> 4); size = ogs_nas_encode_ms_network_feature_support(pkbuf, &attach_request->ms_network_feature_support); @@ -262,8 +247,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -273,8 +257,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_T3324_VALUE_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_T3324_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_T3324_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -284,8 +267,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -295,8 +277,7 @@ int ogs_nas_encode_attach_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message encoded += size; } - if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT) - { + if (attach_request->presencemask & OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -333,8 +314,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) ogs_assert(size >= 0); encoded += size; - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_GUTI_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_GUTI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_GUTI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -344,8 +324,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -355,8 +334,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_MS_IDENTITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -366,8 +344,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_EMM_CAUSE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -377,8 +354,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_T3402_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -388,8 +364,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_T3423_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -399,8 +374,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_EQUIVALENT_PLMNS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -410,8 +384,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE); ogs_assert(size >= 0); encoded += size; @@ -421,8 +394,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE); ogs_assert(size >= 0); encoded += size; @@ -432,8 +404,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT) { attach_accept->additional_update_result.type = (OGS_NAS_ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE >> 4); size = ogs_nas_encode_additional_update_result(pkbuf, &attach_accept->additional_update_result); @@ -441,8 +412,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_T3412_EXTENDED_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -452,8 +422,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_T3324_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -463,8 +432,7 @@ int ogs_nas_encode_attach_accept(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT) - { + if (attach_accept->presencemask & OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -504,8 +472,7 @@ int ogs_nas_encode_attach_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) ogs_assert(size >= 0); encoded += size; - if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT) - { + if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -515,8 +482,7 @@ int ogs_nas_encode_attach_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_T3346_VALUE_PRESENT) - { + if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_T3346_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REJECT_T3346_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -526,8 +492,7 @@ int ogs_nas_encode_attach_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_T3402_VALUE_PRESENT) - { + if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_T3402_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ATTACH_REJECT_T3402_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -537,8 +502,7 @@ int ogs_nas_encode_attach_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message) encoded += size; } - if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_PRESENT) - { + if (attach_reject->presencemask & OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_PRESENT) { attach_reject->extended_emm_cause.type = (OGS_NAS_ATTACH_REJECT_EXTENDED_EMM_CAUSE_TYPE >> 4); size = ogs_nas_encode_extended_emm_cause(pkbuf, &attach_reject->extended_emm_cause); @@ -580,8 +544,7 @@ int ogs_nas_encode_detach_request_to_ue(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *m ogs_assert(size >= 0); encoded += size; - if (detach_request_to_ue->presencemask & OGS_NAS_DETACH_REQUEST_EMM_CAUSE_PRESENT) - { + if (detach_request_to_ue->presencemask & OGS_NAS_DETACH_REQUEST_EMM_CAUSE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DETACH_REQUEST_EMM_CAUSE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -610,8 +573,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess ogs_assert(size >= 0); encoded += size; - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_PRESENT) { tracking_area_update_request->non_current_native_nas_key_set_identifier.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NON_CURRENT_NATIVE_NAS_KEY_SET_IDENTIFIER_TYPE >> 4); size = ogs_nas_encode_key_set_identifier(pkbuf, &tracking_area_update_request->non_current_native_nas_key_set_identifier); @@ -619,8 +581,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_PRESENT) { tracking_area_update_request->gprs_ciphering_key_sequence_number.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_GPRS_CIPHERING_KEY_SEQUENCE_NUMBER_TYPE >> 4); size = ogs_nas_encode_ciphering_key_sequence_number(pkbuf, &tracking_area_update_request->gprs_ciphering_key_sequence_number); @@ -628,8 +589,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -639,8 +599,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_GUTI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -650,8 +609,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_NONCEUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -661,8 +619,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_NETWORK_CAPABILITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -672,8 +629,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -683,8 +639,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DRX_PARAMETER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -694,8 +649,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_PRESENT) { tracking_area_update_request->ue_radio_capability_information_update_needed.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_UE_RADIO_CAPABILITY_INFORMATION_UPDATE_NEEDED_TYPE >> 4); size = ogs_nas_encode_ue_radio_capability_information_update_needed(pkbuf, &tracking_area_update_request->ue_radio_capability_information_update_needed); @@ -703,8 +657,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -714,8 +667,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_CAPABILITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -725,8 +677,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -736,8 +687,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_PRESENT) { tracking_area_update_request->tmsi_status.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_STATUS_TYPE >> 4); size = ogs_nas_encode_tmsi_status(pkbuf, &tracking_area_update_request->tmsi_status); @@ -745,8 +695,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE); ogs_assert(size >= 0); encoded += size; @@ -756,8 +705,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE); ogs_assert(size >= 0); encoded += size; @@ -767,8 +715,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_SUPPORTED_CODECS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -778,8 +725,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT) { tracking_area_update_request->additional_update_type.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE >> 4); size = ogs_nas_encode_additional_update_type(pkbuf, &tracking_area_update_request->additional_update_type); @@ -787,8 +733,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE); ogs_assert(size >= 0); encoded += size; @@ -798,8 +743,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_PRESENT) { tracking_area_update_request->old_guti_type.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_TYPE >> 4); size = ogs_nas_encode_guti_type(pkbuf, &tracking_area_update_request->old_guti_type); @@ -807,8 +751,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_PRESENT) { tracking_area_update_request->device_properties.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &tracking_area_update_request->device_properties); @@ -816,8 +759,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT) { tracking_area_update_request->ms_network_feature_support.type = (OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE >> 4); size = ogs_nas_encode_ms_network_feature_support(pkbuf, &tracking_area_update_request->ms_network_feature_support); @@ -825,8 +767,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -836,8 +777,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3324_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -847,8 +787,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_T3412_EXTENDED_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -858,8 +797,7 @@ int ogs_nas_encode_tracking_area_update_request(ogs_pkbuf_t *pkbuf, ogs_nas_mess encoded += size; } - if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT) - { + if (tracking_area_update_request->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -884,8 +822,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa ogs_assert(size >= 0); encoded += size; - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -895,8 +832,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -906,8 +842,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_TYPE); ogs_assert(size >= 0); encoded += size; @@ -917,8 +852,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -928,8 +862,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_LOCATION_AREA_IDENTIFICATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -939,8 +872,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_MS_IDENTITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -950,8 +882,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMM_CAUSE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -961,8 +892,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -972,8 +902,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -983,8 +912,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EQUIVALENT_PLMNS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -994,8 +922,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EMERGENCY_NUMBER_LIST_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1005,8 +932,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1016,8 +942,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_PRESENT) { tracking_area_update_accept->additional_update_result.type = (OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_ADDITIONAL_UPDATE_RESULT_TYPE >> 4); size = ogs_nas_encode_additional_update_result(pkbuf, &tracking_area_update_accept->additional_update_result); @@ -1025,8 +950,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3412_EXTENDED_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1036,8 +960,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_T3324_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1047,8 +970,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_EXTENDED_DRX_PARAMETERS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1058,8 +980,7 @@ int ogs_nas_encode_tracking_area_update_accept(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_PRESENT) - { + if (tracking_area_update_accept->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT_HEADER_COMPRESSION_CONFIGURATION_STATUS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1084,8 +1005,7 @@ int ogs_nas_encode_tracking_area_update_reject(ogs_pkbuf_t *pkbuf, ogs_nas_messa ogs_assert(size >= 0); encoded += size; - if (tracking_area_update_reject->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_PRESENT) - { + if (tracking_area_update_reject->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_TRACKING_AREA_UPDATE_REJECT_T3346_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1095,8 +1015,7 @@ int ogs_nas_encode_tracking_area_update_reject(ogs_pkbuf_t *pkbuf, ogs_nas_messa encoded += size; } - if (tracking_area_update_reject->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_PRESENT) - { + if (tracking_area_update_reject->presencemask & OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_PRESENT) { tracking_area_update_reject->extended_emm_cause.type = (OGS_NAS_TRACKING_AREA_UPDATE_REJECT_EXTENDED_EMM_CAUSE_TYPE >> 4); size = ogs_nas_encode_extended_emm_cause(pkbuf, &tracking_area_update_reject->extended_emm_cause); @@ -1123,8 +1042,7 @@ int ogs_nas_encode_extended_service_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ ogs_assert(size >= 0); encoded += size; - if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_PRESENT) - { + if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_PRESENT) { extended_service_request->csfb_response.type = (OGS_NAS_EXTENDED_SERVICE_REQUEST_CSFB_RESPONSE_TYPE >> 4); size = ogs_nas_encode_csfb_response(pkbuf, &extended_service_request->csfb_response); @@ -1132,8 +1050,7 @@ int ogs_nas_encode_extended_service_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT) - { + if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EXTENDED_SERVICE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1143,8 +1060,7 @@ int ogs_nas_encode_extended_service_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (extended_service_request->presencemask & OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_PRESENT) { extended_service_request->device_properties.type = (OGS_NAS_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &extended_service_request->device_properties); @@ -1186,8 +1102,7 @@ int ogs_nas_encode_service_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *message ogs_assert(size >= 0); encoded += size; - if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT) - { + if (service_reject->presencemask & OGS_NAS_SERVICE_REJECT_T3346_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SERVICE_REJECT_T3346_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1212,8 +1127,7 @@ int ogs_nas_encode_guti_reallocation_command(ogs_pkbuf_t *pkbuf, ogs_nas_message ogs_assert(size >= 0); encoded += size; - if (guti_reallocation_command->presencemask & OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_PRESENT) - { + if (guti_reallocation_command->presencemask & OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_GUTI_REALLOCATION_COMMAND_TAI_LIST_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1306,8 +1220,7 @@ int ogs_nas_encode_authentication_failure(ogs_pkbuf_t *pkbuf, ogs_nas_message_t ogs_assert(size >= 0); encoded += size; - if (authentication_failure->presencemask & OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT) - { + if (authentication_failure->presencemask & OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_AUTHENTICATION_FAILURE_AUTHENTICATION_FAILURE_PARAMETER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1340,8 +1253,7 @@ int ogs_nas_encode_security_mode_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t * ogs_assert(size >= 0); encoded += size; - if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT) - { + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT) { security_mode_command->imeisv_request.type = (OGS_NAS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_TYPE >> 4); size = ogs_nas_encode_imeisv_request(pkbuf, &security_mode_command->imeisv_request); @@ -1349,8 +1261,7 @@ int ogs_nas_encode_security_mode_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t * encoded += size; } - if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_PRESENT) - { + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1360,8 +1271,7 @@ int ogs_nas_encode_security_mode_command(ogs_pkbuf_t *pkbuf, ogs_nas_message_t * encoded += size; } - if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_PRESENT) - { + if (security_mode_command->presencemask & OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMMAND_NONCEMME_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1382,8 +1292,7 @@ int ogs_nas_encode_security_mode_complete(ogs_pkbuf_t *pkbuf, ogs_nas_message_t ogs_trace("[NAS] Encode SECURITY_MODE_COMPLETE"); - if (security_mode_complete->presencemask & OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT) - { + if (security_mode_complete->presencemask & OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_SECURITY_MODE_COMPLETE_IMEISV_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1434,8 +1343,7 @@ int ogs_nas_encode_emm_information(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *messag ogs_trace("[NAS] Encode EMM_INFORMATION"); - if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT) - { + if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EMM_INFORMATION_FULL_NAME_FOR_NETWORK_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1445,8 +1353,7 @@ int ogs_nas_encode_emm_information(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *messag encoded += size; } - if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT) - { + if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EMM_INFORMATION_SHORT_NAME_FOR_NETWORK_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1456,8 +1363,7 @@ int ogs_nas_encode_emm_information(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *messag encoded += size; } - if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_PRESENT) - { + if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EMM_INFORMATION_LOCAL_TIME_ZONE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1467,8 +1373,7 @@ int ogs_nas_encode_emm_information(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *messag encoded += size; } - if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT) - { + if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EMM_INFORMATION_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1478,8 +1383,7 @@ int ogs_nas_encode_emm_information(ogs_pkbuf_t *pkbuf, ogs_nas_message_t *messag encoded += size; } - if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT) - { + if (emm_information->presencemask & OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_EMM_INFORMATION_NETWORK_DAYLIGHT_SAVING_TIME_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1534,8 +1438,7 @@ int ogs_nas_encode_cs_service_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t ogs_assert(size >= 0); encoded += size; - if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_PRESENT) - { + if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CS_SERVICE_NOTIFICATION_CLI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1545,8 +1448,7 @@ int ogs_nas_encode_cs_service_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_PRESENT) - { + if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CS_SERVICE_NOTIFICATION_SS_CODE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1556,8 +1458,7 @@ int ogs_nas_encode_cs_service_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_PRESENT) - { + if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_INDICATOR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1567,8 +1468,7 @@ int ogs_nas_encode_cs_service_notification(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_PRESENT) - { + if (cs_service_notification->presencemask & OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_CS_SERVICE_NOTIFICATION_LCS_CLIENT_IDENTITY_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1597,8 +1497,7 @@ int ogs_nas_encode_uplink_generic_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_mess ogs_assert(size >= 0); encoded += size; - if (uplink_generic_nas_transport->presencemask & OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) - { + if (uplink_generic_nas_transport->presencemask & OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1627,8 +1526,7 @@ int ogs_nas_encode_downlink_generic_nas_transport(ogs_pkbuf_t *pkbuf, ogs_nas_me ogs_assert(size >= 0); encoded += size; - if (downlink_generic_nas_transport->presencemask & OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) - { + if (downlink_generic_nas_transport->presencemask & OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT_ADDITIONAL_INFORMATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1661,8 +1559,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu ogs_assert(size >= 0); encoded += size; - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1672,8 +1569,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1683,8 +1579,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1694,8 +1589,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) { activate_default_eps_bearer_context_request->radio_priority.type = (OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE >> 4); size = ogs_nas_encode_radio_priority(pkbuf, &activate_default_eps_bearer_context_request->radio_priority); @@ -1703,8 +1597,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1714,8 +1607,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1725,8 +1617,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1736,8 +1627,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1747,8 +1637,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_PRESENT) { activate_default_eps_bearer_context_request->connectivity_type.type = (OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONNECTIVITY_TYPE_TYPE >> 4); size = ogs_nas_encode_connectivity_type(pkbuf, &activate_default_eps_bearer_context_request->connectivity_type); @@ -1756,8 +1645,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) { activate_default_eps_bearer_context_request->wlan_offload_indication.type = (OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE >> 4); size = ogs_nas_encode_wlan_offload_acceptability(pkbuf, &activate_default_eps_bearer_context_request->wlan_offload_indication); @@ -1765,8 +1653,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1776,8 +1663,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1787,8 +1673,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_PRESENT) { activate_default_eps_bearer_context_request->control_plane_only_indication.type = (OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_CONTROL_PLANE_ONLY_INDICATION_TYPE >> 4); size = ogs_nas_encode_control_plane_only_indication(pkbuf, &activate_default_eps_bearer_context_request->control_plane_only_indication); @@ -1796,8 +1681,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1807,8 +1691,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_request(ogs_pkbuf_t *pkbu encoded += size; } - if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_PRESENT) - { + if (activate_default_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_SERVING_PLMN_RATE_CONTROL_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1829,8 +1712,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf ogs_trace("[NAS] Encode ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT"); - if (activate_default_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1840,8 +1722,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf encoded += size; } - if (activate_default_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1866,8 +1747,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_reject(ogs_pkbuf_t *pkbuf ogs_assert(size >= 0); encoded += size; - if (activate_default_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1877,8 +1757,7 @@ int ogs_nas_encode_activate_default_eps_bearer_context_reject(ogs_pkbuf_t *pkbuf encoded += size; } - if (activate_default_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_default_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1911,8 +1790,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk ogs_assert(size >= 0); encoded += size; - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1922,8 +1800,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1933,8 +1810,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1944,8 +1820,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) { activate_dedicated_eps_bearer_context_request->radio_priority.type = (OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE >> 4); size = ogs_nas_encode_radio_priority(pkbuf, &activate_dedicated_eps_bearer_context_request->radio_priority); @@ -1953,8 +1828,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1964,8 +1838,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1975,8 +1848,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) { activate_dedicated_eps_bearer_context_request->wlan_offload_indication.type = (OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE >> 4); size = ogs_nas_encode_wlan_offload_acceptability(pkbuf, &activate_dedicated_eps_bearer_context_request->wlan_offload_indication); @@ -1984,8 +1856,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -1995,8 +1866,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_request(ogs_pkbuf_t *pk encoded += size; } - if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_request->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2017,8 +1887,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_accept(ogs_pkbuf_t *pkb ogs_trace("[NAS] Encode ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT"); - if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2028,8 +1897,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_accept(ogs_pkbuf_t *pkb encoded += size; } - if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT) - { + if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2039,8 +1907,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_accept(ogs_pkbuf_t *pkb encoded += size; } - if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_accept->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2065,8 +1932,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_reject(ogs_pkbuf_t *pkb ogs_assert(size >= 0); encoded += size; - if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2076,8 +1942,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_reject(ogs_pkbuf_t *pkb encoded += size; } - if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT) - { + if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2087,8 +1952,7 @@ int ogs_nas_encode_activate_dedicated_eps_bearer_context_reject(ogs_pkbuf_t *pkb encoded += size; } - if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (activate_dedicated_eps_bearer_context_reject->presencemask & OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2109,8 +1973,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas ogs_trace("[NAS] Encode MODIFY_EPS_BEARER_CONTEXT_REQUEST"); - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_EPS_QOS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2120,8 +1983,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_TFT_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2131,8 +1993,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEW_QOS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2142,8 +2003,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2153,8 +2013,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_PRESENT) { modify_eps_bearer_context_request->radio_priority.type = (OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_TYPE >> 4); size = ogs_nas_encode_radio_priority(pkbuf, &modify_eps_bearer_context_request->radio_priority); @@ -2162,8 +2021,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2173,8 +2031,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2184,8 +2041,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2195,8 +2051,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) { modify_eps_bearer_context_request->wlan_offload_indication.type = (OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE >> 4); size = ogs_nas_encode_wlan_offload_acceptability(pkbuf, &modify_eps_bearer_context_request->wlan_offload_indication); @@ -2204,8 +2059,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2215,8 +2069,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2226,8 +2079,7 @@ int ogs_nas_encode_modify_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_request->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2248,8 +2100,7 @@ int ogs_nas_encode_modify_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf, ogs_nas_ ogs_trace("[NAS] Encode MODIFY_EPS_BEARER_CONTEXT_ACCEPT"); - if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2259,8 +2110,7 @@ int ogs_nas_encode_modify_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf, ogs_nas_ encoded += size; } - if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT) - { + if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2270,8 +2120,7 @@ int ogs_nas_encode_modify_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf, ogs_nas_ encoded += size; } - if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_accept->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2296,8 +2145,7 @@ int ogs_nas_encode_modify_eps_bearer_context_reject(ogs_pkbuf_t *pkbuf, ogs_nas_ ogs_assert(size >= 0); encoded += size; - if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2307,8 +2155,7 @@ int ogs_nas_encode_modify_eps_bearer_context_reject(ogs_pkbuf_t *pkbuf, ogs_nas_ encoded += size; } - if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT) - { + if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2318,8 +2165,7 @@ int ogs_nas_encode_modify_eps_bearer_context_reject(ogs_pkbuf_t *pkbuf, ogs_nas_ encoded += size; } - if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (modify_eps_bearer_context_reject->presencemask & OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2344,8 +2190,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs ogs_assert(size >= 0); encoded += size; - if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2355,8 +2200,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs encoded += size; } - if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_PRESENT) - { + if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_T3396_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2366,8 +2210,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs encoded += size; } - if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) - { + if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_PRESENT) { deactivate_eps_bearer_context_request->wlan_offload_indication.type = (OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_WLAN_OFFLOAD_INDICATION_TYPE >> 4); size = ogs_nas_encode_wlan_offload_acceptability(pkbuf, &deactivate_eps_bearer_context_request->wlan_offload_indication); @@ -2375,8 +2218,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs encoded += size; } - if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2386,8 +2228,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_request(ogs_pkbuf_t *pkbuf, ogs encoded += size; } - if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (deactivate_eps_bearer_context_request->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2408,8 +2249,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf, ogs_ ogs_trace("[NAS] Encode DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT"); - if (deactivate_eps_bearer_context_accept->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (deactivate_eps_bearer_context_accept->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2419,8 +2259,7 @@ int ogs_nas_encode_deactivate_eps_bearer_context_accept(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (deactivate_eps_bearer_context_accept->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (deactivate_eps_bearer_context_accept->presencemask & OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2445,8 +2284,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ ogs_assert(size >= 0); encoded += size; - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT) { pdn_connectivity_request->esm_information_transfer_flag.type = (OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_TYPE >> 4); size = ogs_nas_encode_esm_information_transfer_flag(pkbuf, &pdn_connectivity_request->esm_information_transfer_flag); @@ -2454,8 +2292,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2465,8 +2302,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2476,8 +2312,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_PRESENT) { pdn_connectivity_request->device_properties.type = (OGS_NAS_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &pdn_connectivity_request->device_properties); @@ -2485,8 +2320,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2496,8 +2330,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2507,8 +2340,7 @@ int ogs_nas_encode_pdn_connectivity_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_connectivity_request->presencemask & OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2533,8 +2365,7 @@ int ogs_nas_encode_pdn_connectivity_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t ogs_assert(size >= 0); encoded += size; - if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2544,8 +2375,7 @@ int ogs_nas_encode_pdn_connectivity_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) - { + if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REJECT_BACK_OFF_TIMER_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2555,8 +2385,7 @@ int ogs_nas_encode_pdn_connectivity_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) - { + if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REJECT_RE_ATTEMPT_INDICATOR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2566,8 +2395,7 @@ int ogs_nas_encode_pdn_connectivity_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_PRESENT) - { + if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REJECT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2577,8 +2405,7 @@ int ogs_nas_encode_pdn_connectivity_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_connectivity_reject->presencemask & OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_CONNECTIVITY_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2603,8 +2430,7 @@ int ogs_nas_encode_pdn_disconnect_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t ogs_assert(size >= 0); encoded += size; - if (pdn_disconnect_request->presencemask & OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_disconnect_request->presencemask & OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_DISCONNECT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2614,8 +2440,7 @@ int ogs_nas_encode_pdn_disconnect_request(ogs_pkbuf_t *pkbuf, ogs_nas_message_t encoded += size; } - if (pdn_disconnect_request->presencemask & OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_disconnect_request->presencemask & OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_DISCONNECT_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2640,8 +2465,7 @@ int ogs_nas_encode_pdn_disconnect_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t * ogs_assert(size >= 0); encoded += size; - if (pdn_disconnect_reject->presencemask & OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_disconnect_reject->presencemask & OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_DISCONNECT_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2651,8 +2475,7 @@ int ogs_nas_encode_pdn_disconnect_reject(ogs_pkbuf_t *pkbuf, ogs_nas_message_t * encoded += size; } - if (pdn_disconnect_reject->presencemask & OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (pdn_disconnect_reject->presencemask & OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_PDN_DISCONNECT_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2685,8 +2508,7 @@ int ogs_nas_encode_bearer_resource_allocation_request(ogs_pkbuf_t *pkbuf, ogs_na ogs_assert(size >= 0); encoded += size; - if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2696,8 +2518,7 @@ int ogs_nas_encode_bearer_resource_allocation_request(ogs_pkbuf_t *pkbuf, ogs_na encoded += size; } - if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_PRESENT) { bearer_resource_allocation_request->device_properties.type = (OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &bearer_resource_allocation_request->device_properties); @@ -2705,8 +2526,7 @@ int ogs_nas_encode_bearer_resource_allocation_request(ogs_pkbuf_t *pkbuf, ogs_na encoded += size; } - if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2716,8 +2536,7 @@ int ogs_nas_encode_bearer_resource_allocation_request(ogs_pkbuf_t *pkbuf, ogs_na encoded += size; } - if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_allocation_request->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2742,8 +2561,7 @@ int ogs_nas_encode_bearer_resource_allocation_reject(ogs_pkbuf_t *pkbuf, ogs_nas ogs_assert(size >= 0); encoded += size; - if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2753,8 +2571,7 @@ int ogs_nas_encode_bearer_resource_allocation_reject(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) - { + if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2764,8 +2581,7 @@ int ogs_nas_encode_bearer_resource_allocation_reject(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) - { + if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2775,8 +2591,7 @@ int ogs_nas_encode_bearer_resource_allocation_reject(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_PRESENT) - { + if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2786,8 +2601,7 @@ int ogs_nas_encode_bearer_resource_allocation_reject(ogs_pkbuf_t *pkbuf, ogs_nas encoded += size; } - if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_allocation_reject->presencemask & OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2816,8 +2630,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ ogs_assert(size >= 0); encoded += size; - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2827,8 +2640,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_ESM_CAUSE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2838,8 +2650,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2849,8 +2660,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_PRESENT) { bearer_resource_modification_request->device_properties.type = (OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_TYPE >> 4); size = ogs_nas_encode_device_properties(pkbuf, &bearer_resource_modification_request->device_properties); @@ -2858,8 +2668,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2869,8 +2678,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_HEADER_COMPRESSION_CONFIGURATION_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2880,8 +2688,7 @@ int ogs_nas_encode_bearer_resource_modification_request(ogs_pkbuf_t *pkbuf, ogs_ encoded += size; } - if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_modification_request->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2906,8 +2713,7 @@ int ogs_nas_encode_bearer_resource_modification_reject(ogs_pkbuf_t *pkbuf, ogs_n ogs_assert(size >= 0); encoded += size; - if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2917,8 +2723,7 @@ int ogs_nas_encode_bearer_resource_modification_reject(ogs_pkbuf_t *pkbuf, ogs_n encoded += size; } - if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) - { + if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_BACK_OFF_TIMER_VALUE_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2928,8 +2733,7 @@ int ogs_nas_encode_bearer_resource_modification_reject(ogs_pkbuf_t *pkbuf, ogs_n encoded += size; } - if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) - { + if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_RE_ATTEMPT_INDICATOR_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2939,8 +2743,7 @@ int ogs_nas_encode_bearer_resource_modification_reject(ogs_pkbuf_t *pkbuf, ogs_n encoded += size; } - if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_PRESENT) - { + if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_NBIFOM_CONTAINER_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2950,8 +2753,7 @@ int ogs_nas_encode_bearer_resource_modification_reject(ogs_pkbuf_t *pkbuf, ogs_n encoded += size; } - if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (bearer_resource_modification_reject->presencemask & OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2972,8 +2774,7 @@ int ogs_nas_encode_esm_information_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_ ogs_trace("[NAS] Encode ESM_INFORMATION_RESPONSE"); - if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) - { + if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2983,8 +2784,7 @@ int ogs_nas_encode_esm_information_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -2994,8 +2794,7 @@ int ogs_nas_encode_esm_information_response(ogs_pkbuf_t *pkbuf, ogs_nas_message_ encoded += size; } - if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) - { + if (esm_information_response->presencemask & OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) { size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_ESM_INFORMATION_RESPONSE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS_TYPE); ogs_assert(size >= 0); encoded += size; @@ -3045,8 +2844,7 @@ ogs_pkbuf_t *ogs_nas_emm_encode(ogs_nas_message_t *message) encoded += size; if (message->emm.h.security_header_type >= - OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) - { + OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { ogs_assert(ogs_pkbuf_push(pkbuf, 1)); encoded -= 1; size = ogs_nas_encode_service_request(pkbuf, message); @@ -3056,151 +2854,150 @@ ogs_pkbuf_t *ogs_nas_emm_encode(ogs_nas_message_t *message) goto out; } - switch(message->emm.h.message_type) - { - case OGS_NAS_ATTACH_REQUEST: - size = ogs_nas_encode_attach_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ATTACH_ACCEPT: - size = ogs_nas_encode_attach_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ATTACH_COMPLETE: - size = ogs_nas_encode_attach_complete(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ATTACH_REJECT: - size = ogs_nas_encode_attach_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DETACH_REQUEST: - size = ogs_nas_encode_detach_request_to_ue(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DETACH_ACCEPT: - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST: - size = ogs_nas_encode_tracking_area_update_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT: - size = ogs_nas_encode_tracking_area_update_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_TRACKING_AREA_UPDATE_COMPLETE: - break; - case OGS_NAS_TRACKING_AREA_UPDATE_REJECT: - size = ogs_nas_encode_tracking_area_update_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_EXTENDED_SERVICE_REQUEST: - size = ogs_nas_encode_extended_service_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_SERVICE_REJECT: - size = ogs_nas_encode_service_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_GUTI_REALLOCATION_COMMAND: - size = ogs_nas_encode_guti_reallocation_command(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_GUTI_REALLOCATION_COMPLETE: - break; - case OGS_NAS_AUTHENTICATION_REQUEST: - size = ogs_nas_encode_authentication_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_AUTHENTICATION_RESPONSE: - size = ogs_nas_encode_authentication_response(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_AUTHENTICATION_REJECT: - break; - case OGS_NAS_IDENTITY_REQUEST: - size = ogs_nas_encode_identity_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_IDENTITY_RESPONSE: - size = ogs_nas_encode_identity_response(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_AUTHENTICATION_FAILURE: - size = ogs_nas_encode_authentication_failure(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMMAND: - size = ogs_nas_encode_security_mode_command(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_SECURITY_MODE_COMPLETE: - size = ogs_nas_encode_security_mode_complete(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_SECURITY_MODE_REJECT: - size = ogs_nas_encode_security_mode_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_EMM_STATUS: - size = ogs_nas_encode_emm_status(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_EMM_INFORMATION: - size = ogs_nas_encode_emm_information(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DOWNLINK_NAS_TRANSPORT: - size = ogs_nas_encode_downlink_nas_transport(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_UPLINK_NAS_TRANSPORT: - size = ogs_nas_encode_uplink_nas_transport(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_CS_SERVICE_NOTIFICATION: - size = ogs_nas_encode_cs_service_notification(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT: - size = ogs_nas_encode_uplink_generic_nas_transport(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT: - size = ogs_nas_encode_downlink_generic_nas_transport(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->emm.h.message_type); - ogs_pkbuf_free(pkbuf); - return NULL; + switch (message->emm.h.message_type) { + case OGS_NAS_ATTACH_REQUEST: + size = ogs_nas_encode_attach_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ATTACH_ACCEPT: + size = ogs_nas_encode_attach_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ATTACH_COMPLETE: + size = ogs_nas_encode_attach_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ATTACH_REJECT: + size = ogs_nas_encode_attach_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DETACH_REQUEST: + size = ogs_nas_encode_detach_request_to_ue(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DETACH_ACCEPT: + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REQUEST: + size = ogs_nas_encode_tracking_area_update_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_ACCEPT: + size = ogs_nas_encode_tracking_area_update_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_TRACKING_AREA_UPDATE_COMPLETE: + break; + case OGS_NAS_TRACKING_AREA_UPDATE_REJECT: + size = ogs_nas_encode_tracking_area_update_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_EXTENDED_SERVICE_REQUEST: + size = ogs_nas_encode_extended_service_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SERVICE_REJECT: + size = ogs_nas_encode_service_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_GUTI_REALLOCATION_COMMAND: + size = ogs_nas_encode_guti_reallocation_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_GUTI_REALLOCATION_COMPLETE: + break; + case OGS_NAS_AUTHENTICATION_REQUEST: + size = ogs_nas_encode_authentication_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_RESPONSE: + size = ogs_nas_encode_authentication_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_REJECT: + break; + case OGS_NAS_IDENTITY_REQUEST: + size = ogs_nas_encode_identity_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_IDENTITY_RESPONSE: + size = ogs_nas_encode_identity_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_AUTHENTICATION_FAILURE: + size = ogs_nas_encode_authentication_failure(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMMAND: + size = ogs_nas_encode_security_mode_command(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_COMPLETE: + size = ogs_nas_encode_security_mode_complete(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_SECURITY_MODE_REJECT: + size = ogs_nas_encode_security_mode_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_EMM_STATUS: + size = ogs_nas_encode_emm_status(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_EMM_INFORMATION: + size = ogs_nas_encode_emm_information(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DOWNLINK_NAS_TRANSPORT: + size = ogs_nas_encode_downlink_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_UPLINK_NAS_TRANSPORT: + size = ogs_nas_encode_uplink_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_CS_SERVICE_NOTIFICATION: + size = ogs_nas_encode_cs_service_notification(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_UPLINK_GENERIC_NAS_TRANSPORT: + size = ogs_nas_encode_uplink_generic_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DOWNLINK_GENERIC_NAS_TRANSPORT: + size = ogs_nas_encode_downlink_generic_nas_transport(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->emm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; } out: @@ -3231,120 +3028,119 @@ ogs_pkbuf_t *ogs_nas_esm_encode(ogs_nas_message_t *message) memcpy(pkbuf->data - size, &message->esm.h, size); encoded += size; - switch(message->esm.h.message_type) - { - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_encode_activate_default_eps_bearer_context_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_encode_activate_default_eps_bearer_context_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_encode_activate_default_eps_bearer_context_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_encode_activate_dedicated_eps_bearer_context_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_encode_activate_dedicated_eps_bearer_context_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_encode_activate_dedicated_eps_bearer_context_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_encode_modify_eps_bearer_context_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_encode_modify_eps_bearer_context_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT: - size = ogs_nas_encode_modify_eps_bearer_context_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST: - size = ogs_nas_encode_deactivate_eps_bearer_context_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: - size = ogs_nas_encode_deactivate_eps_bearer_context_accept(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REQUEST: - size = ogs_nas_encode_pdn_connectivity_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_PDN_CONNECTIVITY_REJECT: - size = ogs_nas_encode_pdn_connectivity_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REQUEST: - size = ogs_nas_encode_pdn_disconnect_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_PDN_DISCONNECT_REJECT: - size = ogs_nas_encode_pdn_disconnect_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST: - size = ogs_nas_encode_bearer_resource_allocation_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT: - size = ogs_nas_encode_bearer_resource_allocation_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST: - size = ogs_nas_encode_bearer_resource_modification_request(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT: - size = ogs_nas_encode_bearer_resource_modification_reject(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ESM_INFORMATION_REQUEST: - break; - case OGS_NAS_ESM_INFORMATION_RESPONSE: - size = ogs_nas_encode_esm_information_response(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - case OGS_NAS_ESM_STATUS: - size = ogs_nas_encode_esm_status(pkbuf, message); - ogs_assert(size >= 0); - encoded += size; - break; - default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->esm.h.message_type); - ogs_pkbuf_free(pkbuf); - return NULL; + switch (message->esm.h.message_type) { + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_encode_activate_default_eps_bearer_context_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_encode_activate_default_eps_bearer_context_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_encode_activate_default_eps_bearer_context_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_encode_activate_dedicated_eps_bearer_context_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_encode_activate_dedicated_eps_bearer_context_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_encode_activate_dedicated_eps_bearer_context_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_encode_modify_eps_bearer_context_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_encode_modify_eps_bearer_context_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT: + size = ogs_nas_encode_modify_eps_bearer_context_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST: + size = ogs_nas_encode_deactivate_eps_bearer_context_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT: + size = ogs_nas_encode_deactivate_eps_bearer_context_accept(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REQUEST: + size = ogs_nas_encode_pdn_connectivity_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDN_CONNECTIVITY_REJECT: + size = ogs_nas_encode_pdn_connectivity_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REQUEST: + size = ogs_nas_encode_pdn_disconnect_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_PDN_DISCONNECT_REJECT: + size = ogs_nas_encode_pdn_disconnect_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST: + size = ogs_nas_encode_bearer_resource_allocation_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT: + size = ogs_nas_encode_bearer_resource_allocation_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST: + size = ogs_nas_encode_bearer_resource_modification_request(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT: + size = ogs_nas_encode_bearer_resource_modification_reject(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ESM_INFORMATION_REQUEST: + break; + case OGS_NAS_ESM_INFORMATION_RESPONSE: + size = ogs_nas_encode_esm_information_response(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + case OGS_NAS_ESM_STATUS: + size = ogs_nas_encode_esm_status(pkbuf, message); + ogs_assert(size >= 0); + encoded += size; + break; + default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->esm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; } ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); diff --git a/lib/nas/ies.c b/lib/nas/eps/ies.c similarity index 99% rename from lib/nas/ies.c rename to lib/nas/eps/ies.c index ead71f529..c52995a41 100644 --- a/lib/nas/ies.c +++ b/lib/nas/eps/ies.c @@ -28,11 +28,11 @@ /******************************************************************************* * 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: 2020-04-24 08:50:31.629657 by acetcom + * Created on: 2020-05-21 20:07:15.937289 by acetcom * from 24301-d80.docx ******************************************************************************/ -#include "ogs-nas.h" +#include "ogs-nas-eps.h" int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) { @@ -217,8 +217,7 @@ int ogs_nas_decode_mobile_identity(ogs_nas_mobile_identity_t *mobile_identity, o ogs_assert(ogs_pkbuf_pull(pkbuf, size)); memcpy(mobile_identity, pkbuf->data - size, size); - if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) - { + if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) { mobile_identity->tmsi.tmsi = be32toh(mobile_identity->tmsi.tmsi); } @@ -234,8 +233,7 @@ int ogs_nas_encode_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_mobile_identity_t ogs_nas_mobile_identity_t target; memcpy(&target, mobile_identity, sizeof(ogs_nas_mobile_identity_t)); - if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) - { + if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) { target.tmsi.tmsi = htobe32(mobile_identity->tmsi.tmsi); target.tmsi.spare = 0xf; } @@ -508,8 +506,7 @@ int ogs_nas_decode_eps_mobile_identity(ogs_nas_eps_mobile_identity_t *eps_mobile ogs_assert(ogs_pkbuf_pull(pkbuf, size)); memcpy(eps_mobile_identity, pkbuf->data - size, size); - if (eps_mobile_identity->guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) - { + if (eps_mobile_identity->guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) { eps_mobile_identity->guti.mme_gid = be16toh(eps_mobile_identity->guti.mme_gid); eps_mobile_identity->guti.m_tmsi = be32toh(eps_mobile_identity->guti.m_tmsi); } @@ -526,8 +523,7 @@ int ogs_nas_encode_eps_mobile_identity(ogs_pkbuf_t *pkbuf, ogs_nas_eps_mobile_id ogs_nas_eps_mobile_identity_t target; memcpy(&target, eps_mobile_identity, sizeof(ogs_nas_eps_mobile_identity_t)); - if (target.guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) - { + if (target.guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) { target.guti.spare = 0xf; target.guti.mme_gid = htobe16(eps_mobile_identity->guti.mme_gid); target.guti.m_tmsi = htobe32(eps_mobile_identity->guti.m_tmsi); diff --git a/lib/nas/ies.h b/lib/nas/eps/ies.h similarity index 99% rename from lib/nas/ies.h rename to lib/nas/eps/ies.h index eab4cdb60..6099fddbc 100644 --- a/lib/nas/ies.h +++ b/lib/nas/eps/ies.h @@ -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: 2020-04-24 08:50:31.627584 by acetcom + * Created on: 2020-05-21 20:07:15.935158 by acetcom * from 24301-d80.docx ******************************************************************************/ @@ -36,8 +36,8 @@ #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_IES_H -#define OGS_NAS_IES_H +#ifndef OGS_NAS_EPS_IES_H +#define OGS_NAS_EPS_IES_H #ifdef __cplusplus extern "C" { @@ -231,5 +231,5 @@ int ogs_nas_encode_pdn_address(ogs_pkbuf_t *pkbuf, ogs_nas_pdn_address_t *pdn_ad } #endif -#endif /* OGS_NAS_IES_H */ +#endif /* OGS_NAS_EPS_IES_H */ diff --git a/lib/nas/eps/meson.build b/lib/nas/eps/meson.build new file mode 100644 index 000000000..89932abb3 --- /dev/null +++ b/lib/nas/eps/meson.build @@ -0,0 +1,37 @@ +# Copyright (C) 2019 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 . + +libnas_eps_sources = files(''' + ies.c + decoder.c + encoder.c +'''.split()) + +libnas_eps_inc = include_directories('.') + +libnas_eps = library('ogsnas-eps', + sources : libnas_eps_sources, + version : libogslib_version, + c_args : '-DOGS_NAS_COMPILATION', + include_directories : libnas_eps_inc, + dependencies : libnas_common_dep, + install : true) + +libnas_eps_dep = declare_dependency( + link_with : libnas_eps, + include_directories : libnas_eps_inc, + dependencies : libnas_common_dep) diff --git a/lib/nas/message.h b/lib/nas/eps/message.h similarity index 99% rename from lib/nas/message.h rename to lib/nas/eps/message.h index f597f0b58..08c490d71 100644 --- a/lib/nas/message.h +++ b/lib/nas/eps/message.h @@ -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: 2020-04-24 08:50:31.635873 by acetcom + * Created on: 2020-05-21 20:07:15.943424 by acetcom * from 24301-d80.docx ******************************************************************************/ @@ -36,8 +36,8 @@ #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_MESSAGE_H -#define OGS_NAS_MESSAGE_H +#ifndef OGS_NAS_EPS_MESSAGE_H +#define OGS_NAS_EPS_MESSAGE_H #ifdef __cplusplus extern "C" { @@ -1425,4 +1425,4 @@ ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message); } #endif -#endif /* OGS_NAS_MESSAGE_H */ +#endif /* OGS_NAS_EPS_MESSAGE_H */ diff --git a/lib/nas/eps/ogs-nas-eps.h b/lib/nas/eps/ogs-nas-eps.h new file mode 100644 index 000000000..6d5c0a2dc --- /dev/null +++ b/lib/nas/eps/ogs-nas-eps.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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 . + */ + +#ifndef OGS_NAS_EPS_H +#define OGS_NAS_EPS_H + +#include "ogs-nas-common.h" + +#define OGS_NAS_INSIDE + +#include "nas/eps/types.h" +#include "nas/eps/ies.h" +#include "nas/eps/message.h" + +#undef OGS_NAS_INSIDE + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_NAS_EPS_H */ diff --git a/lib/nas/support/24301-d80.docx b/lib/nas/eps/support/24301-d80.docx similarity index 100% rename from lib/nas/support/24301-d80.docx rename to lib/nas/eps/support/24301-d80.docx diff --git a/lib/nas/support/README.md b/lib/nas/eps/support/README.md similarity index 100% rename from lib/nas/support/README.md rename to lib/nas/eps/support/README.md diff --git a/lib/nas/support/cache/nas-msg-100.py b/lib/nas/eps/support/cache/nas-msg-100.py similarity index 100% rename from lib/nas/support/cache/nas-msg-100.py rename to lib/nas/eps/support/cache/nas-msg-100.py diff --git a/lib/nas/support/cache/nas-msg-101.py b/lib/nas/eps/support/cache/nas-msg-101.py similarity index 100% rename from lib/nas/support/cache/nas-msg-101.py rename to lib/nas/eps/support/cache/nas-msg-101.py diff --git a/lib/nas/support/cache/nas-msg-104.py b/lib/nas/eps/support/cache/nas-msg-104.py similarity index 100% rename from lib/nas/support/cache/nas-msg-104.py rename to lib/nas/eps/support/cache/nas-msg-104.py diff --git a/lib/nas/support/cache/nas-msg-193.py b/lib/nas/eps/support/cache/nas-msg-193.py similarity index 100% rename from lib/nas/support/cache/nas-msg-193.py rename to lib/nas/eps/support/cache/nas-msg-193.py diff --git a/lib/nas/support/cache/nas-msg-194.py b/lib/nas/eps/support/cache/nas-msg-194.py similarity index 100% rename from lib/nas/support/cache/nas-msg-194.py rename to lib/nas/eps/support/cache/nas-msg-194.py diff --git a/lib/nas/support/cache/nas-msg-195.py b/lib/nas/eps/support/cache/nas-msg-195.py similarity index 100% rename from lib/nas/support/cache/nas-msg-195.py rename to lib/nas/eps/support/cache/nas-msg-195.py diff --git a/lib/nas/support/cache/nas-msg-197.py b/lib/nas/eps/support/cache/nas-msg-197.py similarity index 100% rename from lib/nas/support/cache/nas-msg-197.py rename to lib/nas/eps/support/cache/nas-msg-197.py diff --git a/lib/nas/support/cache/nas-msg-198.py b/lib/nas/eps/support/cache/nas-msg-198.py similarity index 100% rename from lib/nas/support/cache/nas-msg-198.py rename to lib/nas/eps/support/cache/nas-msg-198.py diff --git a/lib/nas/support/cache/nas-msg-199.py b/lib/nas/eps/support/cache/nas-msg-199.py similarity index 100% rename from lib/nas/support/cache/nas-msg-199.py rename to lib/nas/eps/support/cache/nas-msg-199.py diff --git a/lib/nas/support/cache/nas-msg-201.py b/lib/nas/eps/support/cache/nas-msg-201.py similarity index 100% rename from lib/nas/support/cache/nas-msg-201.py rename to lib/nas/eps/support/cache/nas-msg-201.py diff --git a/lib/nas/support/cache/nas-msg-202.py b/lib/nas/eps/support/cache/nas-msg-202.py similarity index 100% rename from lib/nas/support/cache/nas-msg-202.py rename to lib/nas/eps/support/cache/nas-msg-202.py diff --git a/lib/nas/support/cache/nas-msg-203.py b/lib/nas/eps/support/cache/nas-msg-203.py similarity index 100% rename from lib/nas/support/cache/nas-msg-203.py rename to lib/nas/eps/support/cache/nas-msg-203.py diff --git a/lib/nas/support/cache/nas-msg-205.py b/lib/nas/eps/support/cache/nas-msg-205.py similarity index 100% rename from lib/nas/support/cache/nas-msg-205.py rename to lib/nas/eps/support/cache/nas-msg-205.py diff --git a/lib/nas/support/cache/nas-msg-206.py b/lib/nas/eps/support/cache/nas-msg-206.py similarity index 100% rename from lib/nas/support/cache/nas-msg-206.py rename to lib/nas/eps/support/cache/nas-msg-206.py diff --git a/lib/nas/support/cache/nas-msg-208.py b/lib/nas/eps/support/cache/nas-msg-208.py similarity index 100% rename from lib/nas/support/cache/nas-msg-208.py rename to lib/nas/eps/support/cache/nas-msg-208.py diff --git a/lib/nas/support/cache/nas-msg-209.py b/lib/nas/eps/support/cache/nas-msg-209.py similarity index 100% rename from lib/nas/support/cache/nas-msg-209.py rename to lib/nas/eps/support/cache/nas-msg-209.py diff --git a/lib/nas/support/cache/nas-msg-210.py b/lib/nas/eps/support/cache/nas-msg-210.py similarity index 100% rename from lib/nas/support/cache/nas-msg-210.py rename to lib/nas/eps/support/cache/nas-msg-210.py diff --git a/lib/nas/support/cache/nas-msg-211.py b/lib/nas/eps/support/cache/nas-msg-211.py similarity index 100% rename from lib/nas/support/cache/nas-msg-211.py rename to lib/nas/eps/support/cache/nas-msg-211.py diff --git a/lib/nas/support/cache/nas-msg-212.py b/lib/nas/eps/support/cache/nas-msg-212.py similarity index 100% rename from lib/nas/support/cache/nas-msg-212.py rename to lib/nas/eps/support/cache/nas-msg-212.py diff --git a/lib/nas/support/cache/nas-msg-213.py b/lib/nas/eps/support/cache/nas-msg-213.py similarity index 100% rename from lib/nas/support/cache/nas-msg-213.py rename to lib/nas/eps/support/cache/nas-msg-213.py diff --git a/lib/nas/support/cache/nas-msg-214.py b/lib/nas/eps/support/cache/nas-msg-214.py similarity index 100% rename from lib/nas/support/cache/nas-msg-214.py rename to lib/nas/eps/support/cache/nas-msg-214.py diff --git a/lib/nas/support/cache/nas-msg-215.py b/lib/nas/eps/support/cache/nas-msg-215.py similarity index 100% rename from lib/nas/support/cache/nas-msg-215.py rename to lib/nas/eps/support/cache/nas-msg-215.py diff --git a/lib/nas/support/cache/nas-msg-74.py b/lib/nas/eps/support/cache/nas-msg-217.py similarity index 100% rename from lib/nas/support/cache/nas-msg-74.py rename to lib/nas/eps/support/cache/nas-msg-217.py diff --git a/lib/nas/support/cache/nas-msg-218.py b/lib/nas/eps/support/cache/nas-msg-218.py similarity index 100% rename from lib/nas/support/cache/nas-msg-218.py rename to lib/nas/eps/support/cache/nas-msg-218.py diff --git a/lib/nas/support/cache/nas-msg-232.py b/lib/nas/eps/support/cache/nas-msg-232.py similarity index 100% rename from lib/nas/support/cache/nas-msg-232.py rename to lib/nas/eps/support/cache/nas-msg-232.py diff --git a/lib/nas/support/cache/nas-msg-65.py b/lib/nas/eps/support/cache/nas-msg-65.py similarity index 100% rename from lib/nas/support/cache/nas-msg-65.py rename to lib/nas/eps/support/cache/nas-msg-65.py diff --git a/lib/nas/support/cache/nas-msg-66.py b/lib/nas/eps/support/cache/nas-msg-66.py similarity index 100% rename from lib/nas/support/cache/nas-msg-66.py rename to lib/nas/eps/support/cache/nas-msg-66.py diff --git a/lib/nas/support/cache/nas-msg-67.py b/lib/nas/eps/support/cache/nas-msg-67.py similarity index 100% rename from lib/nas/support/cache/nas-msg-67.py rename to lib/nas/eps/support/cache/nas-msg-67.py diff --git a/lib/nas/support/cache/nas-msg-68.py b/lib/nas/eps/support/cache/nas-msg-68.py similarity index 100% rename from lib/nas/support/cache/nas-msg-68.py rename to lib/nas/eps/support/cache/nas-msg-68.py diff --git a/lib/nas/support/cache/nas-msg-69.1.py b/lib/nas/eps/support/cache/nas-msg-69.1.py similarity index 100% rename from lib/nas/support/cache/nas-msg-69.1.py rename to lib/nas/eps/support/cache/nas-msg-69.1.py diff --git a/lib/nas/support/cache/nas-msg-69.2.py b/lib/nas/eps/support/cache/nas-msg-69.2.py similarity index 100% rename from lib/nas/support/cache/nas-msg-69.2.py rename to lib/nas/eps/support/cache/nas-msg-69.2.py diff --git a/lib/nas/support/cache/nas-msg-81.py b/lib/nas/eps/support/cache/nas-msg-70.py similarity index 100% rename from lib/nas/support/cache/nas-msg-81.py rename to lib/nas/eps/support/cache/nas-msg-70.py diff --git a/lib/nas/support/cache/nas-msg-72.py b/lib/nas/eps/support/cache/nas-msg-72.py similarity index 100% rename from lib/nas/support/cache/nas-msg-72.py rename to lib/nas/eps/support/cache/nas-msg-72.py diff --git a/lib/nas/support/cache/nas-msg-73.py b/lib/nas/eps/support/cache/nas-msg-73.py similarity index 100% rename from lib/nas/support/cache/nas-msg-73.py rename to lib/nas/eps/support/cache/nas-msg-73.py diff --git a/lib/nas/support/cache/nas-msg-84.py b/lib/nas/eps/support/cache/nas-msg-74.py similarity index 100% rename from lib/nas/support/cache/nas-msg-84.py rename to lib/nas/eps/support/cache/nas-msg-74.py diff --git a/lib/nas/support/cache/nas-msg-75.py b/lib/nas/eps/support/cache/nas-msg-75.py similarity index 100% rename from lib/nas/support/cache/nas-msg-75.py rename to lib/nas/eps/support/cache/nas-msg-75.py diff --git a/lib/nas/support/cache/nas-msg-76.py b/lib/nas/eps/support/cache/nas-msg-76.py similarity index 100% rename from lib/nas/support/cache/nas-msg-76.py rename to lib/nas/eps/support/cache/nas-msg-76.py diff --git a/lib/nas/support/cache/nas-msg-77.1.py b/lib/nas/eps/support/cache/nas-msg-77.1.py similarity index 100% rename from lib/nas/support/cache/nas-msg-77.1.py rename to lib/nas/eps/support/cache/nas-msg-77.1.py diff --git a/lib/nas/support/cache/nas-msg-78.py b/lib/nas/eps/support/cache/nas-msg-78.py similarity index 100% rename from lib/nas/support/cache/nas-msg-78.py rename to lib/nas/eps/support/cache/nas-msg-78.py diff --git a/lib/nas/support/cache/nas-msg-80.py b/lib/nas/eps/support/cache/nas-msg-80.py similarity index 100% rename from lib/nas/support/cache/nas-msg-80.py rename to lib/nas/eps/support/cache/nas-msg-80.py diff --git a/lib/nas/eps/support/cache/nas-msg-81.py b/lib/nas/eps/support/cache/nas-msg-81.py new file mode 100644 index 000000000..bdf2b4880 --- /dev/null +++ b/lib/nas/eps/support/cache/nas-msg-81.py @@ -0,0 +1,2 @@ +ies = [] +msg_list[key]["ies"] = ies diff --git a/lib/nas/support/cache/nas-msg-82.py b/lib/nas/eps/support/cache/nas-msg-82.py similarity index 100% rename from lib/nas/support/cache/nas-msg-82.py rename to lib/nas/eps/support/cache/nas-msg-82.py diff --git a/lib/nas/support/cache/nas-msg-83.py b/lib/nas/eps/support/cache/nas-msg-83.py similarity index 100% rename from lib/nas/support/cache/nas-msg-83.py rename to lib/nas/eps/support/cache/nas-msg-83.py diff --git a/lib/nas/eps/support/cache/nas-msg-84.py b/lib/nas/eps/support/cache/nas-msg-84.py new file mode 100644 index 000000000..bdf2b4880 --- /dev/null +++ b/lib/nas/eps/support/cache/nas-msg-84.py @@ -0,0 +1,2 @@ +ies = [] +msg_list[key]["ies"] = ies diff --git a/lib/nas/support/cache/nas-msg-85.py b/lib/nas/eps/support/cache/nas-msg-85.py similarity index 100% rename from lib/nas/support/cache/nas-msg-85.py rename to lib/nas/eps/support/cache/nas-msg-85.py diff --git a/lib/nas/support/cache/nas-msg-86.py b/lib/nas/eps/support/cache/nas-msg-86.py similarity index 100% rename from lib/nas/support/cache/nas-msg-86.py rename to lib/nas/eps/support/cache/nas-msg-86.py diff --git a/lib/nas/support/cache/nas-msg-92.py b/lib/nas/eps/support/cache/nas-msg-92.py similarity index 100% rename from lib/nas/support/cache/nas-msg-92.py rename to lib/nas/eps/support/cache/nas-msg-92.py diff --git a/lib/nas/support/cache/nas-msg-93.py b/lib/nas/eps/support/cache/nas-msg-93.py similarity index 100% rename from lib/nas/support/cache/nas-msg-93.py rename to lib/nas/eps/support/cache/nas-msg-93.py diff --git a/lib/nas/support/cache/nas-msg-94.py b/lib/nas/eps/support/cache/nas-msg-94.py similarity index 100% rename from lib/nas/support/cache/nas-msg-94.py rename to lib/nas/eps/support/cache/nas-msg-94.py diff --git a/lib/nas/support/cache/nas-msg-95.py b/lib/nas/eps/support/cache/nas-msg-95.py similarity index 100% rename from lib/nas/support/cache/nas-msg-95.py rename to lib/nas/eps/support/cache/nas-msg-95.py diff --git a/lib/nas/support/cache/nas-msg-96.py b/lib/nas/eps/support/cache/nas-msg-96.py similarity index 100% rename from lib/nas/support/cache/nas-msg-96.py rename to lib/nas/eps/support/cache/nas-msg-96.py diff --git a/lib/nas/support/cache/nas-msg-97.py b/lib/nas/eps/support/cache/nas-msg-97.py similarity index 100% rename from lib/nas/support/cache/nas-msg-97.py rename to lib/nas/eps/support/cache/nas-msg-97.py diff --git a/lib/nas/support/cache/nas-msg-98.py b/lib/nas/eps/support/cache/nas-msg-98.py similarity index 100% rename from lib/nas/support/cache/nas-msg-98.py rename to lib/nas/eps/support/cache/nas-msg-98.py diff --git a/lib/nas/support/cache/nas-msg-99.py b/lib/nas/eps/support/cache/nas-msg-99.py similarity index 100% rename from lib/nas/support/cache/nas-msg-99.py rename to lib/nas/eps/support/cache/nas-msg-99.py diff --git a/lib/nas/support/nas-message.py b/lib/nas/eps/support/nas-message.py similarity index 91% rename from lib/nas/support/nas-message.py rename to lib/nas/eps/support/nas-message.py index d9a0b9df5..3c48be462 100644 --- a/lib/nas/support/nas-message.py +++ b/lib/nas/eps/support/nas-message.py @@ -350,8 +350,8 @@ f.write("""#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_IES_H -#define OGS_NAS_IES_H +#ifndef OGS_NAS_EPS_IES_H +#define OGS_NAS_EPS_IES_H #ifdef __cplusplus extern "C" { @@ -374,14 +374,14 @@ f.write("""#ifdef __cplusplus } #endif -#endif /* OGS_NAS_IES_H */ +#endif /* OGS_NAS_EPS_IES_H */ """) f.close() f = open(outdir + 'ies.c', 'w') output_header_to_file(f) -f.write("""#include "ogs-nas.h" +f.write("""#include "ogs-nas-eps.h" int ogs_nas_encode_optional_type(ogs_pkbuf_t *pkbuf, uint8_t type) { @@ -398,7 +398,7 @@ for (k, v) in sorted_type_list: # d_print("%s = %s\n" % (k, type_list[k])) f.write("/* %s %s\n" % (type_list[k]["reference"], k)) f.write(" * %s %s %s */\n" % (type_list[k]["presence"], type_list[k]["format"], type_list[k]["length"])) - if type_list[k]["format"] == "TV" and type_list[k]["length"] == "1": + if (type_list[k]["format"] == "TV" or type_list[k]["format"] == "T") and type_list[k]["length"] == "1": f.write("int ogs_nas_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(" memcpy(%s, pkbuf->data - 1, 1);\n\n" % v_lower(k)) @@ -512,8 +512,8 @@ f.write("""#if !defined(OGS_NAS_INSIDE) && !defined(OGS_NAS_COMPILATION) #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_MESSAGE_H -#define OGS_NAS_MESSAGE_H +#ifndef OGS_NAS_EPS_MESSAGE_H +#define OGS_NAS_EPS_MESSAGE_H #ifdef __cplusplus extern "C" { @@ -647,7 +647,7 @@ ogs_pkbuf_t *ogs_nas_plain_encode(ogs_nas_message_t *message); } #endif -#endif /* OGS_NAS_MESSAGE_H */ +#endif /* OGS_NAS_EPS_MESSAGE_H */ """) f.close() @@ -656,7 +656,7 @@ f.close() f = open(outdir + 'decoder.c', 'w') output_header_to_file(f) -f.write("""#include "ogs-nas.h" +f.write("""#include "ogs-nas-eps.h" """) @@ -690,8 +690,7 @@ for (k, v) in sorted_msg_list: optional_fields = False; for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: if optional_fields is False: - f.write(""" while(pkbuf->len > 0) - { + f.write(""" while (pkbuf->len > 0) { uint8_t *buffer = pkbuf->data; uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer); @@ -699,22 +698,21 @@ for (k, v) in sorted_msg_list: ogs_assert(ogs_pkbuf_pull(pkbuf, size)); decoded += size; - switch(type) - { + switch (type) { """) optional_fields = True; - f.write(" case OGS_NAS_%s_%s_TYPE:\n" % (v_upper(k), v_upper(ie["value"]))) - f.write(" size = ogs_nas_decode_%s(&%s->%s, pkbuf);\n" % (v_lower(ie["type"]), v_lower(k), v_lower(ie["value"]))) - f.write(" ogs_assert(size >= 0);\n") - f.write(" %s->presencemask |= OGS_NAS_%s_%s_PRESENT;\n" % (v_lower(k), v_upper(k), v_upper(ie["value"]))) - f.write(" decoded += size;\n") - f.write(" break;\n") + f.write(" case OGS_NAS_%s_%s_TYPE:\n" % (v_upper(k), v_upper(ie["value"]))) + f.write(" size = ogs_nas_decode_%s(&%s->%s, pkbuf);\n" % (v_lower(ie["type"]), v_lower(k), v_lower(ie["value"]))) + f.write(" ogs_assert(size >= 0);\n") + f.write(" %s->presencemask |= OGS_NAS_%s_%s_PRESENT;\n" % (v_lower(k), v_upper(k), v_upper(ie["value"]))) + f.write(" decoded += size;\n") + f.write(" break;\n") if [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: - f.write(""" default: - ogs_warn("Unknown type(0x%x) or not implemented\\n", type); - break; + f.write(""" default: + ogs_warn("Unknown type(0x%x) or not implemented\\n", type); + break; } } @@ -741,8 +739,7 @@ f.write("""int ogs_nas_emm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf decoded += size; if (message->emm.h.security_header_type >= - OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) - { + OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { ogs_assert(ogs_pkbuf_push(pkbuf, 1)); decoded -= 1; size = ogs_nas_decode_service_request(message, pkbuf); @@ -752,24 +749,23 @@ f.write("""int ogs_nas_emm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf goto out; } - switch(message->emm.h.message_type) - { + switch (message->emm.h.message_type) { """) for (k, v) in sorted_msg_list: if "ies" not in msg_list[k]: continue; if float(msg_list[k]["type"]) < 192 and k.find("TO UE") == -1 and k != "SERVICE REQUEST": - f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) if len(msg_list[k]["ies"]) != 0: - f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) - f.write(" ogs_assert(size >= 0);\n") - f.write(" decoded += size;\n") - f.write(" break;\n") + f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" decoded += size;\n") + f.write(" break;\n") -f.write(""" default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->emm.h.message_type); - break; +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->emm.h.message_type); + break; } out: @@ -795,24 +791,23 @@ f.write("""int ogs_nas_esm_decode(ogs_nas_message_t *message, ogs_pkbuf_t *pkbuf memcpy(&message->esm.h, pkbuf->data - size, size); decoded += size; - switch(message->esm.h.message_type) - { + switch (message->esm.h.message_type) { """) for (k, v) in sorted_msg_list: if "ies" not in msg_list[k]: continue; if float(msg_list[k]["type"]) >= 192: - f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) if len(msg_list[k]["ies"]) != 0: - f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) - f.write(" ogs_assert(size >= 0);\n") - f.write(" decoded += size;\n") - f.write(" break;\n") + f.write(" size = ogs_nas_decode_%s(message, pkbuf);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" decoded += size;\n") + f.write(" break;\n") -f.write(""" default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->esm.h.message_type); - break; +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->esm.h.message_type); + break; } ogs_assert(ogs_pkbuf_push(pkbuf, decoded)); @@ -826,7 +821,7 @@ f.close() f = open(outdir + 'encoder.c', 'w') output_header_to_file(f) -f.write("""#include "ogs-nas.h" +f.write("""#include "ogs-nas-eps.h" """) @@ -858,10 +853,11 @@ for (k, v) in sorted_msg_list: f.write(" encoded += size;\n\n") for ie in [ies for ies in msg_list[k]["ies"] if ies["presence"] == "O"]: - f.write(" if (%s->presencemask & OGS_NAS_%s_%s_PRESENT)\n" % (v_lower(k), v_upper(k), v_upper(ie["value"]))) - f.write(" {\n") + f.write(" if (%s->presencemask & OGS_NAS_%s_%s_PRESENT) {\n" % (v_lower(k), v_upper(k), v_upper(ie["value"]))) if ie["length"] == "1" and ie["format"] == "TV": f.write(" %s->%s.type = (OGS_NAS_%s_%s_TYPE >> 4);\n\n" % (v_lower(k), v_lower(ie["value"]), v_upper(k), v_upper(ie["value"]))) + elif ie["length"] == "1" and ie["format"] == "T": + f.write(" %s->%s.type = OGS_NAS_%s_%s_TYPE;\n\n" % (get_value(k), get_value(ie["value"]), v_upper(k), v_upper(ie["value"]))) else: f.write(" size = ogs_nas_encode_optional_type(pkbuf, OGS_NAS_%s_%s_TYPE);\n" % (v_upper(k), v_upper(ie["value"]))) f.write(" ogs_assert(size >= 0);\n") @@ -899,8 +895,7 @@ f.write("""ogs_pkbuf_t *ogs_nas_emm_encode(ogs_nas_message_t *message) encoded += size; if (message->emm.h.security_header_type >= - OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) - { + OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { ogs_assert(ogs_pkbuf_push(pkbuf, 1)); encoded -= 1; size = ogs_nas_encode_service_request(pkbuf, message); @@ -910,26 +905,25 @@ f.write("""ogs_pkbuf_t *ogs_nas_emm_encode(ogs_nas_message_t *message) goto out; } - switch(message->emm.h.message_type) - { + switch (message->emm.h.message_type) { """) for (k, v) in sorted_msg_list: if "ies" not in msg_list[k]: continue; if float(msg_list[k]["type"]) < 192 and k.find("FROM UE") == -1 and k != "SERVICE REQUEST": - f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) if len(msg_list[k]["ies"]) != 0: - f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) - f.write(" ogs_assert(size >= 0);\n") - f.write(" encoded += size;\n") - f.write(" break;\n") + f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n") + f.write(" break;\n") -f.write(""" default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->emm.h.message_type); - ogs_pkbuf_free(pkbuf); - return NULL; +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->emm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; } out: @@ -962,26 +956,25 @@ f.write("""ogs_pkbuf_t *ogs_nas_esm_encode(ogs_nas_message_t *message) memcpy(pkbuf->data - size, &message->esm.h, size); encoded += size; - switch(message->esm.h.message_type) - { + switch (message->esm.h.message_type) { """) for (k, v) in sorted_msg_list: if "ies" not in msg_list[k]: continue; if float(msg_list[k]["type"]) >= 192: - f.write(" case OGS_NAS_%s:\n" % v_upper(k)) + f.write(" case OGS_NAS_%s:\n" % v_upper(k)) if len(msg_list[k]["ies"]) != 0: - f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) - f.write(" ogs_assert(size >= 0);\n") - f.write(" encoded += size;\n") - f.write(" break;\n") + f.write(" size = ogs_nas_encode_%s(pkbuf, message);\n" % v_lower(k)) + f.write(" ogs_assert(size >= 0);\n") + f.write(" encoded += size;\n") + f.write(" break;\n") -f.write(""" default: - ogs_error("Unknown message type (0x%x) or not implemented", - message->esm.h.message_type); - ogs_pkbuf_free(pkbuf); - return NULL; +f.write(""" default: + ogs_error("Unknown message type (0x%x) or not implemented", + message->esm.h.message_type); + ogs_pkbuf_free(pkbuf); + return NULL; } ogs_assert(ogs_pkbuf_push(pkbuf, encoded)); diff --git a/lib/nas/support/type-list.py b/lib/nas/eps/support/type-list.py similarity index 95% rename from lib/nas/support/type-list.py rename to lib/nas/eps/support/type-list.py index 1f699538f..582289b0a 100644 --- a/lib/nas/support/type-list.py +++ b/lib/nas/eps/support/type-list.py @@ -32,26 +32,22 @@ type_list["Tracking area identity"]["encode"] = \ " target.tac = htobe16(tracking_area_identity->tac);\n\n" type_list["Mobile identity"]["decode"] = \ -" if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI)\n" \ -" {\n" \ +" if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) {\n" \ " mobile_identity->tmsi.tmsi = be32toh(mobile_identity->tmsi.tmsi);\n" \ " }\n\n" type_list["Mobile identity"]["encode"] = \ -" if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI)\n" \ -" {\n" \ +" if (mobile_identity->tmsi.type == OGS_NAS_MOBILE_IDENTITY_TMSI) {\n" \ " target.tmsi.tmsi = htobe32(mobile_identity->tmsi.tmsi);\n" \ " target.tmsi.spare = 0xf;\n" \ " }\n\n" type_list["EPS mobile identity"]["decode"] = \ -" if (eps_mobile_identity->guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI)\n" \ -" {\n" \ +" if (eps_mobile_identity->guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) {\n" \ " eps_mobile_identity->guti.mme_gid = be16toh(eps_mobile_identity->guti.mme_gid);\n" \ " eps_mobile_identity->guti.m_tmsi = be32toh(eps_mobile_identity->guti.m_tmsi);\n" \ " }\n\n" type_list["EPS mobile identity"]["encode"] = \ -" if (target.guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI)\n" \ -" {\n" \ +" if (target.guti.type == OGS_NAS_EPS_MOBILE_IDENTITY_GUTI) {\n" \ " target.guti.spare = 0xf;\n" \ " target.guti.mme_gid = htobe16(eps_mobile_identity->guti.mme_gid);\n" \ " target.guti.m_tmsi = htobe32(eps_mobile_identity->guti.m_tmsi);\n" \ diff --git a/lib/nas/types.h b/lib/nas/eps/types.h similarity index 55% rename from lib/nas/types.h rename to lib/nas/eps/types.h index bbfc5a58a..397762f6f 100644 --- a/lib/nas/types.h +++ b/lib/nas/eps/types.h @@ -21,68 +21,13 @@ #error "This header cannot be included directly." #endif -#ifndef OGS_NAS_TYPES_H -#define OGS_NAS_TYPES_H - -#include "ogs-core.h" +#ifndef OGS_NAS_EPS_TYPES_H +#define OGS_NAS_EPS_TYPES_H #ifdef __cplusplus extern "C" { #endif -#define OGS_NAS_CLEAR_DATA(__dATA) \ - do { \ - ogs_assert((__dATA)); \ - if ((__dATA)->buffer) { \ - ogs_free((__dATA)->buffer); \ - (__dATA)->buffer = NULL; \ - (__dATA)->length = 0; \ - } \ - } while(0) -#define OGS_NAS_STORE_DATA(__dST, __sRC) \ - do { \ - ogs_assert((__sRC)); \ - ogs_assert((__sRC)->buffer); \ - ogs_assert((__dST)); \ - OGS_NAS_CLEAR_DATA(__dST); \ - (__dST)->length = (__sRC)->length; \ - (__dST)->buffer = ogs_calloc((__dST)->length, sizeof(uint8_t)); \ - memcpy((__dST)->buffer, (__sRC)->buffer, (__dST)->length); \ - } while(0) - -#define OGS_NAS_KSI_NO_KEY_IS_AVAILABLE 0x7 - -/********************************** - * NAS PLMN_ID Structure */ -typedef struct ogs_nas_plmn_id_s { -ED2(uint8_t mcc2:4;, - uint8_t mcc1:4;) -ED2(uint8_t mnc3:4;, - uint8_t mcc3:4;) -ED2(uint8_t mnc2:4;, - uint8_t mnc1:4;) -} __attribute__ ((packed)) ogs_nas_plmn_id_t; - -void *ogs_nas_from_plmn_id( - ogs_nas_plmn_id_t *ogs_nas_plmn_id, ogs_plmn_id_t *plmn_id); -void *ogs_nas_to_plmn_id( - ogs_plmn_id_t *plmn_id, ogs_nas_plmn_id_t *ogs_nas_plmn_id); - -typedef struct ogs_nas_guti_s { - ogs_nas_plmn_id_t nas_plmn_id; - uint16_t mme_gid; - uint8_t mme_code; - uint32_t m_tmsi; -} __attribute__ ((packed)) ogs_nas_guti_t; - -/* 9.9.2.0 Additional information - * O TLV 3-n */ -#define NAX_MAX_ADDITIONAL_INFORMATION_LEN 255 -typedef struct ogs_nas_additional_information_s { - uint8_t length; - uint8_t buffer[NAX_MAX_ADDITIONAL_INFORMATION_LEN]; -} __attribute__ ((packed)) ogs_nas_additional_information_t; - /* 9.9.2.0A Device properties * See subclause 10.5.7.8 in 3GPP TS 24.008 [13]. * O TV 1 */ @@ -92,28 +37,6 @@ ED3(uint8_t type:4;, uint8_t low_priority:1;) } __attribute__ ((packed)) ogs_nas_device_properties_t; -/* 9.9.2.1 EPS bearer context status - * O TLV 4 */ -typedef struct ogs_nas_eps_bearer_context_status_s { - uint8_t length; -ED8(uint8_t ebi7:1;, - uint8_t ebi6:1;, - uint8_t ebi5:1;, - uint8_t ebi4:1;, - uint8_t ebi3:1;, - uint8_t ebi2:1;, - uint8_t ebi1:1;, - uint8_t ebi0:1;) -ED8(uint8_t ebi15:1;, - uint8_t ebi14:1;, - uint8_t ebi13:1;, - uint8_t ebi12:1;, - uint8_t ebi11:1;, - uint8_t ebi10:1;, - uint8_t ebi9:1;, - uint8_t ebi8:1;) -} __attribute__ ((packed)) ogs_nas_eps_bearer_context_status_t; - /* 9.9.2.2 Location area identification * See subclause 10.5.1.3 in 3GPP TS 24.008 [13] * O TV 6 */ @@ -124,124 +47,6 @@ typedef struct ogs_nas_location_area_identification_s { typedef ogs_nas_location_area_identification_t ogs_nas_lai_t; -/* 9.9.2.3 Mobile identity - * See subclause 10.5.1.4 in 3GPP TS 24.008 [13]. - * O TLV 7-10 */ -#define OGS_NAS_MOBILE_IDENTITY_NONE 0 -#define OGS_NAS_MOBILE_IDENTITY_IMSI 1 -#define OGS_NAS_MOBILE_IDENTITY_IMEI 2 -#define OGS_NAS_MOBILE_IDENTITY_IMEISV 3 -#define OGS_NAS_MOBILE_IDENTITY_TMSI 4 -#define OGS_NAS_MOBILE_IDENTITY_TMGI 5 -#define OGS_NAS_MOBILE_IDENTITY_GUTI 6 -typedef struct ogs_nas_mobile_identity_imsi_s { -ED3(uint8_t digit1:4;, - uint8_t odd_even:1;, - uint8_t type:3;) -ED2(uint8_t digit3:4;, - uint8_t digit2:4;) -ED2(uint8_t digit5:4;, - uint8_t digit4:4;) -ED2(uint8_t digit7:4;, - uint8_t digit6:4;) -ED2(uint8_t digit9:4;, - uint8_t digit8:4;) -ED2(uint8_t digit11:4;, - uint8_t digit10:4;) -ED2(uint8_t digit13:4;, - uint8_t digit12:4;) -ED2(uint8_t digit15:4;, - uint8_t digit14:4;) -} __attribute__ ((packed)) ogs_nas_mobile_identity_imsi_t; - -typedef struct ogs_nas_mobile_identity_tmsi_s { -ED3(uint8_t spare:4;, - uint8_t odd_even:1;, - uint8_t type:3;) - uint32_t tmsi; -} __attribute__ ((packed)) ogs_nas_mobile_identity_tmsi_t; - -typedef struct ogs_nas_mobile_identity_tmgi_s { -ED5(uint8_t spare:2;, - uint8_t mbms_session_id:1;, - uint8_t mcc_mnc:1;, - uint8_t odd_even:1;, - uint8_t type:3;) - uint8_t mbms_servicec_id[3]; - ogs_nas_plmn_id_t nas_plmn_id; - uint8_t mbms_session_identity; -} __attribute__ ((packed)) ogs_nas_mobile_identity_tmgi_t; - -typedef struct ogs_nas_mobile_identity_imeisv_s { -ED3(uint8_t digit1:4;, - uint8_t odd_even:1;, - uint8_t type:3;) -ED2(uint8_t digit3:4;, - uint8_t digit2:4;) -ED2(uint8_t digit5:4;, - uint8_t digit4:4;) -ED2(uint8_t digit7:4;, - uint8_t digit6:4;) -ED2(uint8_t digit9:4;, - uint8_t digit8:4;) -ED2(uint8_t digit11:4;, - uint8_t digit10:4;) -ED2(uint8_t digit13:4;, - uint8_t digit12:4;) -ED2(uint8_t digit15:4;, - uint8_t digit14:4;) -ED2(uint8_t digit17:4;, - uint8_t digit16:4;) -} __attribute__ ((packed)) ogs_nas_mobile_identity_imeisv_t; - -typedef struct ogs_nas_mobile_identity_s { - uint8_t length; - union { - ogs_nas_mobile_identity_imsi_t imsi; - ogs_nas_mobile_identity_tmsi_t tmsi; - ogs_nas_mobile_identity_tmgi_t tmgi; - ogs_nas_mobile_identity_imeisv_t imeisv; - }; -} ogs_nas_mobile_identity_t; - -/* 9.9.2.4 Mobile station classmark 2 - * See subclause 10.5.1.6 in 3GPP TS 24.008 - * O TLV 5 */ -#define OGS_NAS_MS_CLASSMARK_2_REVISION_GSM_PHASE1 0 -#define OGS_NAS_MS_CLASSMARK_2_REVISION_GSM_PHASE2 1 -#define OGS_NAS_MS_CLASSMARK_2_REVISION_R99 2 -#define OGS_NAS_MS_CLASSMARK_2_REVISION_RESERVED 2 - -#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS1 0 -#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS2 1 -#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS3 2 -#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS4 3 -#define OGS_NAS_MS_CLASSMARK_2_RF_CLASS5 4 -#define OGS_NAS_MS_CLASSMARK_2_RF_IRRELEVANT 7 -typedef struct ogs_nas_mobile_station_classmark_2_t { - uint8_t length; -ED5(uint8_t spare1:1;, - uint8_t revision_level:2;, - uint8_t es_ind:1;, - uint8_t a5_1:1;, - uint8_t rf_power_capability:3;) -ED7(uint8_t spare:1;, - uint8_t ps_capa:1;, - uint8_t ss_screen_indicator:2;, - uint8_t sm_capabi:1;, - uint8_t vbs:1;, - uint8_t vgcs:1;, - uint8_t fc:1;) -ED8(uint8_t cm3:1;, - uint8_t spare2:1;, - uint8_t lcsva_cap:1;, - uint8_t ucs2:1;, - uint8_t solsa:1;, - uint8_t cmsp:1;, - uint8_t a5_3:1;, - uint8_t a5_2:1;) -} __attribute__ ((packed)) ogs_nas_mobile_station_classmark_2_t; - /*9.9.2.5 Mobile station classmark 3 * See subclause 10.5.1.7 in 3GPP TS 24.008 [13]. * O TLV 2-34 */ @@ -251,30 +56,6 @@ typedef struct ogs_nas_mobile_station_classmark_3_s { uint8_t buffer[OGS_NAS_MAX_MOBILE_STATION_CLASSMARK_3_LEN]; } __attribute__ ((packed)) ogs_nas_mobile_station_classmark_3_t; -/* 9.9.2.8 PLMN list - * See subclause 10.5.1.13 in 3GPP TS 24.008 [13]. - * O TLV 5-47 */ -#define OGS_NAS_MAX_PLMN 15 -typedef struct ogs_nas_plmn_list_s { - uint8_t length; - ogs_nas_plmn_id_t nas_plmn_id[OGS_NAS_MAX_PLMN]; -} __attribute__ ((packed)) ogs_nas_plmn_list_t; - -/* 9.9.2.10 Supported codec list - * See subclause 10.5.4.32 in 3GPP TS 24.008 [13]. - * O TLV 5-n */ -typedef struct ogs_nas_supported_codec_item_s { - uint8_t system_identification; - uint8_t length_of_bitmap; - uint16_t codec_bitmap; -} __attribute__ ((packed)) ogs_nas_supported_codec_item_t; - -#define OGS_NAS_MAX_SUPPORTED_CODECS 8 -typedef struct ogs_nas_supported_codec_list_s { - uint8_t length; - ogs_nas_supported_codec_item_t item[OGS_NAS_MAX_SUPPORTED_CODECS]; -} __attribute__ ((packed)) ogs_nas_supported_codec_list_t; - /* 9.9.3.0A Additional update result * O TV 1 */ typedef struct ogs_nas_additional_update_result_s { @@ -296,36 +77,6 @@ ED4(uint8_t type:4;, uint8_t autv:1;) } __attribute__ ((packed)) ogs_nas_additional_update_type_t; -/* 9.9.3.1 Authentication failure parameter - * See subclause 10.5.3.2.2 in 3GPP TS 24.008 [13]. - * O TLV 16 */ -typedef struct ogs_nas_authentication_failure_parameter_s { - uint8_t length; - uint8_t auts[OGS_AUTS_LEN]; -} __attribute__ ((packed)) ogs_nas_authentication_failure_parameter_t; - -/* 9.9.3.2 Authentication parameter AUTN - * See subclause 10.5.3.1.1 in 3GPP TS 24.008 [13]. - * M LV 17 */ -typedef struct ogs_nas_authentication_parameter_autn_s { - uint8_t length; - uint8_t autn[OGS_AUTN_LEN]; -} ogs_nas_authentication_parameter_autn_t; - -/* 9.9.3.3 Authentication parameter RAND - * See subclause 10.5.3.1 in 3GPP TS 24.008 [13]. - * M V 16 */ -typedef struct ogs_nas_authentication_parameter_rand_s { - uint8_t rand[OGS_RAND_LEN]; -} ogs_nas_authentication_parameter_rand_t; - -/* 9.9.3.4 Authentication response parameter - * M LV 5-17 */ -typedef struct ogs_nas_authentication_response_parameter_s { - uint8_t length; - uint8_t res[OGS_MAX_RES_LEN]; -} ogs_nas_authentication_response_parameter_t; - /* 9.9.3.4a Ciphering key sequence number * See subclause 10.5.1.2 in 3GPP TS 24.008 [13]. * O TV 1 */ @@ -346,18 +97,6 @@ ED3(uint8_t type:4;, uint8_t response:3;) } __attribute__ ((packed)) ogs_nas_csfb_response_t; -/* 9.9.3.6 Daylight saving time - * See subclause 10.5.3.12 in 3GPP TS 24.008 [13]. - * O TLV 3 */ -#define OGS_NAS_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 0 -#define OGS_NAS_PLUS_1_HOUR_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 1 -#define OGS_NAS_PLUS_2_HOURS_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME 2 -typedef struct ogs_nas_daylight_saving_time_s { - uint8_t length; -ED2(uint8_t spare:6;, - uint8_t value:2;) -} __attribute__ ((packed)) ogs_nas_daylight_saving_time_t; - /* 9.9.3.7 Detach type * M V 1/2 * 9.9.3.21 NAS key set identifier @@ -400,7 +139,7 @@ ED3(uint8_t cn_specific_drx_cycle_length_coefficient_and_drx_value_for_s1_mode:4 /* 9.9.3.9 EMM cause * O TV 2 - * Annex A (informative):
Cause values for EPS mobility management + * Annex A (informative) Cause values for EPS mobility management * A.1 Causes related to UE identification */ #define EMM_CAUSE_IMSI_UNKNOWN_IN_HSS 2 #define EMM_CAUSE_ILLEGAL_UE 3 @@ -479,9 +218,6 @@ ED4(uint8_t tsc:1;, #define OGS_NAS_EPS_MOBILE_IDENTITY_IMSI 1 #define OGS_NAS_EPS_MOBILE_IDENTITY_GUTI 6 #define OGS_NAS_EPS_MOBILE_IDENTITY_IMEI 3 - -#define OGS_NAS_EPS_MOBILE_IDENTITY_EVEN 0 -#define OGS_NAS_EPS_MOBILE_IDENTITY_ODD 1 typedef struct ogs_nas_eps_mobile_identity_guti_s { ED3(uint8_t spare:4;, uint8_t odd_even:1;, @@ -491,16 +227,12 @@ ED3(uint8_t spare:4;, uint8_t mme_code; uint32_t m_tmsi; } __attribute__ ((packed)) ogs_nas_eps_mobile_identity_guti_t; - -typedef ogs_nas_mobile_identity_imsi_t ogs_nas_eps_mobile_identity_imsi_t; -typedef ogs_nas_eps_mobile_identity_imsi_t ogs_nas_eps_mobile_identity_imei_t; - typedef struct ogs_nas_eps_mobile_identity_s { uint8_t length; union { - ogs_nas_eps_mobile_identity_imsi_t imsi; + ogs_nas_mobile_identity_imsi_t imsi; ogs_nas_eps_mobile_identity_guti_t guti; - ogs_nas_eps_mobile_identity_imei_t imei; + ogs_nas_mobile_identity_imei_t imei; }; } __attribute__ ((packed)) ogs_nas_eps_mobile_identity_t; @@ -555,44 +287,6 @@ typedef struct ogs_nas_esm_message_container_s { uint8_t *buffer; } ogs_nas_esm_message_container_t; -/* 9.9.3.16 GPRS timer - * See subclause 10.5.7.3 in 3GPP TS 24.008 [13]. - * M V 1 or O TV 2 */ -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_2_SS 0 -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM 1 -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH 2 -#define OGS_NAS_GRPS_TIMER_UNIT_DEACTIVATED 7 -typedef struct ogs_nas_gprs_timer_s { -ED2(uint8_t unit:3;, - uint8_t value:5;) -} __attribute__ ((packed)) ogs_nas_gprs_timer_t; - -/* 9.9.3.16A GPRS timer 2 - * See subclause 10.5.7.4 in 3GPP TS 24.008 [13]. - * O TLV 3 */ -typedef struct ogs_nas_gprs_timer_2_s { - uint8_t length; - uint8_t gprs_timer_2_value; -} __attribute__ ((packed)) ogs_nas_gprs_timer_2_t; - -/* 9.9.3.16B GPRS timer 3 - * See subclause 10.5.7.4a in 3GPP TS 24.008 [13]. - * O TLV 3 */ -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_MM 0 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_HH 1 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_HH 2 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_2_SS 3 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_30_SS 4 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_MM 5 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_320_HH 6 -#define OGS_NAS_GRPS_TIMER_3_UNIT_DEACTIVATED 7 - -typedef struct ogs_nas_gprs_timer_3_s { - uint8_t length; -ED2(uint8_t unit:3;, - uint8_t timer_value:5;) -} __attribute__ ((packed)) ogs_nas_gprs_timer_3_t; - /* 9.9.3.17 Identity type 2 * See subclause 10.5.5.9 in 3GPP TS 24.008 [13]. * M V 1/2 */ @@ -605,18 +299,6 @@ ED2(uint8_t spare:5;, uint8_t type:3;) } __attribute__ ((packed)) ogs_nas_identity_type_2_t; -/* 9.9.3.18 IMEISV request - * See subclause 10.5.5.10 in 3GPP TS 24.008 [13]. - * O TV 1 */ -typedef struct ogs_nas_imeisv_request_s { -#define OGS_NAS_IMEISV_TYPE 0xc -ED3(uint8_t type:4;, - uint8_t spare:1;, -#define OGS_NAS_IMEISV_NOT_REQUESTED 0 -#define OGS_NAS_IMEISV_REQUESTED 1 - uint8_t imeisv_request_value:3;) -} __attribute__ ((packed)) ogs_nas_imeisv_request_t; - /* 9.9.3.19 KSI and sequence number * M V 1 */ typedef struct ogs_nas_ksi_and_sequence_number_s { @@ -670,16 +352,6 @@ ED3(uint8_t type:4;, uint8_t extended_periodic_timers:1;) } __attribute__ ((packed)) ogs_nas_ms_network_feature_support_t; -/* 9.9.3.21 NAS key set identifier - * M V 1/2 - * 9.9.2.9 Spare half octet - * M V 1/2 */ -typedef struct ogs_nas_key_set_identifier_s { -ED3(uint8_t type:4;, - uint8_t tsc:1;, - uint8_t nas_key_set_identifier:3;) -} __attribute__ ((packed)) ogs_nas_key_set_identifier_t; - /* 9.9.3.22 message container * M LV 3-252 */ #define OGS_NAS_MAX_MESSAGE_CONTAINER_LEN 250 @@ -705,19 +377,6 @@ ED4(uint8_t spare1:1;, uint8_t type_of_integrity_protection_algorithm:3;) } __attribute__ ((packed)) ogs_nas_security_algorithms_t; -/* 9.9.3.24 Network name - * See subclause 10.5.3.5a in 3GPP TS 24.008 [13]. - * O TLV 3-n */ -#define OGS_NAS_MAX_NETWORK_NAME_LEN 255 -typedef struct ogs_nas_network_name_s { - uint8_t length; -ED4(uint8_t ext:1;, - uint8_t coding_scheme:3;, - uint8_t add_ci:1;, - uint8_t number_of_spare_bits_in_last_octet:3;) - uint8_t name[OGS_NAS_MAX_NETWORK_NAME_LEN]; -} __attribute__ ((packed)) ogs_nas_network_name_t; - /* 9.9.3.24A Network resource identifier container * See subclause 10.5.5.31 in 3GPP TS 24.008 [13]. * O TLV 4 */ @@ -772,31 +431,6 @@ ED3(uint8_t tsc:1;, * M V 2 */ typedef uint16_t ogs_nas_short_mac_t; -/* 9.9.3.29 Time zone - * See subclause 10.5.3.8 in 3GPP TS 24.008 [13]. - * O TV 2 */ -typedef uint8_t ogs_nas_time_zone_t; - -/* 9.9.3.30 Time zone and time - * See subclause 10.5.3.9 in 3GPP TS 24.008 [13]. - * 9.2.3.11 TPServiceCentreTimeStamp (TPSCTS) in 3GPP TS 23.040 [90] - * O TV 8 */ -#define OGS_OGS_NAS_TIME_TO_BCD(x) OGS_TIME_TO_BCD(x) -typedef struct ogs_nas_time_zone_and_time_s { - uint8_t year; - uint8_t mon; - uint8_t mday; - uint8_t hour; - uint8_t min; - uint8_t sec; - /* The Time Zone indicates the difference, expressed in quarters of an hour, - * between the local time and GMT. In the first of the two semi-octets, - * the first bit (bit 3 of the seventh octet of - * the TP-Service-Centre-Time-Stamp field) represents - * the algebraic sign of this difference (0: positive, 1: negative). */ - uint8_t timezone; -} ogs_nas_time_zone_and_time_t; - /* 9.9.3.31 TMSI status * See subclause 10.5.5.4 in 3GPP TS 24.008 [13] * O TV 1 */ @@ -806,135 +440,6 @@ ED3(uint8_t type:4;, uint8_t tmsi_flag:1;) } __attribute__ ((packed)) ogs_nas_tmsi_status_t; -/* 9.9.3.32 Tracking area identity - * O TV 6 */ -typedef struct ogs_nas_tracking_area_identity_s { - ogs_nas_plmn_id_t nas_plmn_id; - uint16_t tac; -} __attribute__ ((packed)) ogs_nas_tracking_area_identity_t; - -typedef ogs_nas_tracking_area_identity_t ogs_nas_tai_t; - -/* 9.9.3.33 Tracking area identity list - * M LV 7-97 */ -#define OGS_NAS_MAX_TAI_LIST_LEN 96 -#define TAI0_TYPE 0 -#define TAI1_TYPE 1 -#define TAI2_TYPE 2 -typedef struct tai0_list_s { - struct { - ED3(uint8_t spare:1;, - uint8_t type:2;, - uint8_t num:5;) - /* - * Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'. - * Use 'ogs_plmn_id_t' for easy implementation. - * ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t) - * and is sent to the UE. - */ - ogs_plmn_id_t plmn_id; - uint16_t tac[OGS_MAX_NUM_OF_TAI]; - } __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI]; -} __attribute__ ((packed)) tai0_list_t; - -typedef struct tai2_list_s { -ED3(uint8_t spare:1;, - uint8_t type:2;, - uint8_t num:5;) - /* - * Do not change 'ogs_tai_t' to 'ogs_nas_tracking_area_identity_t'. - * Use 'ogs_tai_t' for easy implementation. - * ogs_nas_tai_list_build() changes to NAS format(ogs_nas_tracking_area_identity_t) - * and is sent to the UE. - */ - ogs_tai_t tai[OGS_MAX_NUM_OF_TAI]; -} __attribute__ ((packed)) tai2_list_t; - -typedef struct ogs_nas_tracking_area_identity_list_s { - uint8_t length; - uint8_t buffer[OGS_NAS_MAX_TAI_LIST_LEN]; -} __attribute__ ((packed)) ogs_nas_tracking_area_identity_list_t; - -void ogs_nas_tai_list_build( - ogs_nas_tracking_area_identity_list_t *target, - tai0_list_t *source0, tai2_list_t *source2); - -/* 9.9.3.34 UE network capability - * M LV 3-14 */ -typedef struct ogs_nas_ue_network_capability_s { - uint8_t length; - union { - struct { - ED8(uint8_t eea0:1;, - uint8_t eea1:1;, - uint8_t eea2:1;, - uint8_t eea3:1;, - uint8_t eea4:1;, - uint8_t eea5:1;, - uint8_t eea6:1;, - uint8_t eea7:1;) - }; - uint8_t eea; - }; - union { - struct { - ED8(uint8_t eia0:1;, - uint8_t eia1:1;, - uint8_t eia2:1;, - uint8_t eia3:1;, - uint8_t eia4:1;, - uint8_t eia5:1;, - uint8_t eia6:1;, - uint8_t eia7:1;) - }; - uint8_t eia; - }; - union { - struct { - ED8(uint8_t uea0:1;, - uint8_t uea1:1;, - uint8_t uea2:1;, - uint8_t uea3:1;, - uint8_t uea4:1;, - uint8_t uea5:1;, - uint8_t uea6:1;, - uint8_t uea7:1;) - }; - uint8_t uea; - }; - union { - struct { - ED8(uint8_t ucs2:1;, - uint8_t uia1:1;, - uint8_t uia2:1;, - uint8_t uia3:1;, - uint8_t uia4:1;, - uint8_t uia5:1;, - uint8_t uia6:1;, - uint8_t uia7:1;) - }; - uint8_t uia; - }; -ED8(uint8_t prose_dd:1;, - uint8_t prose:1;, - uint8_t h_245_ash:1;, - uint8_t acc_csfb:1;, - uint8_t lpp:1;, - uint8_t lcs:1;, - uint8_t srvcc:1;, - uint8_t nf:1;) -ED8(uint8_t epco:1;, - uint8_t hc_cp_ciot:1;, - uint8_t erw_opdn:1;, - uint8_t s1u_data:1;, - uint8_t up_ciot:1;, - uint8_t cp_ciot:1;, - uint8_t prose_relay:1;, - uint8_t prose_dc:1;) -ED2(uint8_t spare:7;, - uint8_t multiple_drb:1;) -} __attribute__ ((packed)) ogs_nas_ue_network_capability_t; - /* 9.9.3.35 UE radio capability information update needed * O TV 1 */ typedef struct ogs_nas_ue_radio_capability_information_update_needed_s { @@ -943,85 +448,13 @@ ED3(uint8_t type:4;, uint8_t update_needed:1;) } __attribute__ ((packed)) ogs_nas_ue_radio_capability_information_update_needed_t; +/* 9.9.3.34 UE network capability + * M LV 3-14 */ +typedef struct ogs_nas_s1_ue_network_capability_s ogs_nas_ue_network_capability_t; + /* 9.9.3.36 UE security capability * M LV 3-6 */ -typedef struct ogs_nas_ue_security_capability_s { - uint8_t length; - union { - struct { - ED8(uint8_t eea0:1;, - uint8_t eea1:1;, - uint8_t eea2:1;, - uint8_t eea3:1;, - uint8_t eea4:1;, - uint8_t eea5:1;, - uint8_t eea6:1;, - uint8_t eea7:1;) - }; - uint8_t eea; - }; - union { - struct { - ED8(uint8_t eia0:1;, - uint8_t eia1:1;, - uint8_t eia2:1;, - uint8_t eia3:1;, - uint8_t eia4:1;, - uint8_t eia5:1;, - uint8_t eia6:1;, - uint8_t eia7:1;) - }; - uint8_t eia; - }; - union { - struct { - ED8(uint8_t uea0:1;, - uint8_t uea1:1;, - uint8_t uea2:1;, - uint8_t uea3:1;, - uint8_t uea4:1;, - uint8_t uea5:1;, - uint8_t uea6:1;, - uint8_t uea7:1;) - }; - uint8_t uea; - }; - union { - struct { - ED8(uint8_t spare1:1;, - uint8_t uia1:1;, - uint8_t uia2:1;, - uint8_t uia3:1;, - uint8_t uia4:1;, - uint8_t uia5:1;, - uint8_t uia6:1;, - uint8_t uia7:1;) - }; - uint8_t uia; - }; - union { - struct { - ED8(uint8_t spare2:1;, - uint8_t gea1:1;, - uint8_t gea2:1;, - uint8_t gea3:1;, - uint8_t gea4:1;, - uint8_t gea5:1;, - uint8_t gea6:1;, - uint8_t gea7:1;) - }; - uint8_t gea; - }; -} __attribute__ ((packed)) ogs_nas_ue_security_capability_t; - -/* buffer : 9.9.3.37 Emergency number list - * See subclause 10.5.3.13 in 3GPP TS 24.008 [13]. - * O TLV 5-50 */ -#define OGS_NAS_MAX_EMERGENCY_NUMBER_LIST_LEN 48 -typedef struct ogs_nas_emergency_number_list_s { - uint16_t length; - uint8_t buffer[OGS_NAS_MAX_EMERGENCY_NUMBER_LIST_LEN]; -} __attribute__ ((packed)) ogs_nas_emergency_number_list_t; +typedef struct ogs_nas_s1_ue_security_capability_s ogs_nas_ue_security_capability_t; /* 9.9.3.38 CLI * O TLV 3-14 @@ -1084,15 +517,6 @@ ED3(uint8_t type:4;, uint8_t guti_type:1;) } __attribute__ ((packed)) ogs_nas_guti_type_t; -/* 9.9.3.46 Extended DRX parameters - * See subclause 10.5.5.32 in 3GPP TS 24.008 [13]. - * O TLV 3 */ -typedef struct ogs_nas_extended_drx_parameters_s { - uint8_t length; -ED2(uint8_t paging_time_window:4;, - uint8_t e_drx_value:4;) -} __attribute__ ((packed)) ogs_nas_extended_drx_parameters_t; - /* 9.9.4.1 Access point name * See subclause 10.5.6.1 in 3GPP TS 24.008 [13]. * O TLV 3-102 */ @@ -1101,22 +525,6 @@ typedef struct ogs_nas_access_point_name_s { char apn[OGS_MAX_APN_LEN]; } __attribute__ ((packed)) ogs_nas_access_point_name_t; -/* 9.9.4.2 APN aggregate maximum bit rate - * O TLV 4-8 */ -typedef struct ogs_nas_apn_aggregate_maximum_bit_rate_s { - uint8_t length; - uint8_t dl_apn_ambr; - uint8_t ul_apn_ambr; - uint8_t dl_apn_ambr_extended; - uint8_t ul_apn_ambr_extended; - uint8_t dl_apn_ambr_extended2; - uint8_t ul_apn_ambr_extended2; -} __attribute__ ((packed)) ogs_nas_apn_aggregate_maximum_bit_rate_t; - -void apn_ambr_build( - ogs_nas_apn_aggregate_maximum_bit_rate_t * apn_aggregate_maximum_bit_rate, - uint32_t dl_ambr, uint32_t ul_ambr); - /* 9.9.4.2A Connectivity type * See subclause 10.5.6.19 in 3GPP TS 24.008 [13]. * O TV 1 */ @@ -1126,32 +534,9 @@ ED3(uint8_t type:4;, uint8_t considered_lipa_pdn_connection:1;) } __attribute__ ((packed)) ogs_nas_connectivity_type_t; -/* 9.9.4.3 EPS quality of service - * M LV 2-14 */ -typedef struct ogs_nas_eps_quality_of_service_s { - uint8_t length; - uint8_t qci; - uint8_t ul_mbr; - uint8_t dl_mbr; - uint8_t ul_gbr; - uint8_t dl_gbr; - uint8_t ul_mbr_extended; - uint8_t dl_mbr_extended; - uint8_t ul_gbr_extended; - uint8_t dl_gbr_extended; - uint8_t ul_mbr_extended2; - uint8_t dl_mbr_extended2; - uint8_t ul_gbr_extended2; - uint8_t dl_gbr_extended2; -} ogs_nas_eps_quality_of_service_t; - -void eps_qos_build(ogs_nas_eps_quality_of_service_t *eps_qos, - uint8_t qci, - uint64_t dl_mbr, uint64_t ul_mbr, uint64_t dl_gbr, uint64_t ul_gbr); - /* 9.9.4.4 ESM cause * M V 1 - * Annex B (informative):
Cause values for EPS session management + * Annex B (informative) Cause values for EPS session management B.1 Causes related to nature of request */ #define ESM_CAUSE_OPERATOR_DETERMINED_BARRING 8 #define ESM_CAUSE_INSUFFICIENT_RESOURCES 26 @@ -1284,15 +669,6 @@ typedef struct ogs_nas_quality_of_service_s { uint8_t buffer[OGS_NAS_QOS_LEN]; } __attribute__ ((packed)) ogs_nas_quality_of_service_t; -/* 9.9.4.13A Re-attempt indicator - * O TLV 3 */ -typedef struct ogs_nas_re_attempt_indicator_s { - uint8_t length; -ED3(uint8_t spare:3;, /* allowed in A/Gb mode or Iu mode */ - uint8_t eplmnc:1;, /* allowed in an equivalent PLMN */ - uint8_t ratc:1;) -} __attribute__ ((packed)) ogs_nas_re_attempt_indicator_t; - /* 9.9.4.14 Request type * M V 1/2 * See subclause 10.5.6.17 in 3GPP TS 24.008 [13]. @@ -1348,56 +724,6 @@ ED4(uint8_t type:4;, uint8_t e_utran_via_wlan_acceptable:1;) } __attribute__ ((packed)) ogs_nas_wlan_offload_acceptability_t; -/* 9.9.4.19 NBIFOM container - * See subclause 10.5.6.21 in 3GPP TS 24.008 [4]. - * O TLV 3-257 */ -#define MAX_OGS_NAS_NBIFOM_CONTAINER_LEN 255 -typedef struct ogs_nas_nbifom_container_s { - uint8_t length; - uint8_t buffer[MAX_OGS_NAS_NBIFOM_CONTAINER_LEN]; -} __attribute__ ((packed)) ogs_nas_nbifom_container_t; - -/* 9.9.4.22 Header compression configuration - * O TLV 5-257 */ -#define MAX_OGS_NAS_HEADER_COMPRESSION_CONTAINER_LEN 251 -typedef struct ogs_nas_header_compression_configuration_s { - uint8_t length; -ED8(uint8_t spare:1;, - uint8_t profile0x0104:1;, - uint8_t profile0x0103:1;, - uint8_t profile0x0102:1;, - uint8_t profile0x0006:1;, - uint8_t profile0x0004:1;, - uint8_t profile0x0003:1;, - uint8_t profile0x0002:1;) - uint16_t max_cid; -#define OGS_NAS_HEADER_COMPRESSION_NO_COMPRESSION 0 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0002_UDP_IP 1 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0003_ESP_IP 2 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0004 3 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0006 4 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0102_UDP_IP 5 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0103_ESP_IP 6 -#define OGS_NAS_HEADER_COMPRESSION_PROFILE_0x0104_IP 7 - uint8_t type; - uint8_t container[MAX_OGS_NAS_NBIFOM_CONTAINER_LEN]; -} __attribute__ ((packed)) ogs_nas_header_compression_configuration_t; - -/* 9.9.4.23 Control plane only indication - * O TV 1 */ -typedef struct ogs_nas_control_plane_only_indication_s { -ED3(uint8_t type:4;, - uint8_t spare:3;, - uint8_t ciot_eps_optimization:1;) -} __attribute__ ((packed)) ogs_nas_control_plane_only_indication_t; - -/* 9.9.4.26 Extended protocol configuration options - * O TLV-E 4-65538 */ -typedef struct ogs_nas_extended_protocol_configuration_options_s { - uint16_t length; - uint8_t *buffer; -} __attribute__ ((packed)) ogs_nas_extended_protocol_configuration_options_t; - /* 9.9.4.27 Header compression configuration status * O TLV 4 */ typedef struct ogs_nas_header_compression_configuration_status_s { @@ -1405,31 +731,9 @@ typedef struct ogs_nas_header_compression_configuration_status_s { uint16_t value; } __attribute__ ((packed)) ogs_nas_header_compression_configuration_status_t; -/* 9.9.4.28 Serving PLMN rate control - * O TLV 4 */ -typedef struct ogs_nas_serving_plmn_rate_control_s { - uint8_t length; -ED8(uint8_t ebi7:1;, - uint8_t ebi6:1;, - uint8_t ebi5:1;, - uint8_t ebi4:1;, - uint8_t ebi3:1;, - uint8_t ebi2:1;, - uint8_t ebi1:1;, - uint8_t ebi0:1;) -ED8(uint8_t ebi15:1;, - uint8_t ebi14:1;, - uint8_t ebi13:1;, - uint8_t ebi12:1;, - uint8_t ebi11:1;, - uint8_t ebi10:1;, - uint8_t ebi9:1;, - uint8_t ebi8:1;) -} __attribute__ ((packed)) ogs_nas_serving_plmn_rate_control_t; - #ifdef __cplusplus } #endif -#endif /* OGS_NAS_TYPES_H */ +#endif /* OGS_NAS_EPS_TYPES_H */ diff --git a/lib/nas/meson.build b/lib/nas/meson.build index c5762059d..a99fddc8f 100644 --- a/lib/nas/meson.build +++ b/lib/nas/meson.build @@ -15,32 +15,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -libnas_sources = files(''' - ogs-nas.h - - ies.h - types.h - conv.h - message.h - - ies.c - types.c - conv.c - decoder.c - encoder.c -'''.split()) - -libnas_inc = include_directories('.') - -libnas = library('ogsnas', - sources : libnas_sources, - version : libogslib_version, - c_args : '-DOGS_NAS_COMPILATION', - include_directories : [libnas_inc, libcrypt_inc, libinc], - dependencies : libcore_dep, - install : true) - -libnas_dep = declare_dependency( - link_with : libnas, - include_directories : [libnas_inc, libcrypt_inc, libinc], - dependencies : libcore_dep) +subdir('common') +subdir('5gs') +subdir('eps') diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 484721da1..1d259c943 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -85,7 +85,7 @@ ogs_pkbuf_t *emm_build_attach_accept( if (mme_ue->guti_present) { attach_accept->presencemask |= OGS_NAS_ATTACH_ACCEPT_GUTI_PRESENT; nas_guti->length = sizeof(ogs_nas_eps_mobile_identity_guti_t); - nas_guti->guti.odd_even = OGS_NAS_EPS_MOBILE_IDENTITY_EVEN; + nas_guti->guti.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN; nas_guti->guti.type = OGS_NAS_EPS_MOBILE_IDENTITY_GUTI; nas_guti->guti.nas_plmn_id = mme_ue->guti.nas_plmn_id; nas_guti->guti.mme_gid = mme_ue->guti.mme_gid; @@ -250,7 +250,7 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue) mme_ue->selected_enc_algorithm; nas_key_set_identifier->tsc = 0; - nas_key_set_identifier->nas_key_set_identifier = 0; + nas_key_set_identifier->value = 0; replayed_ue_security_capabilities->eea = mme_ue->ue_network_capability.eea; replayed_ue_security_capabilities->eia = mme_ue->ue_network_capability.eia; diff --git a/src/mme/meson.build b/src/mme/meson.build index 0281c3202..78050ef62 100644 --- a/src/mme/meson.build +++ b/src/mme/meson.build @@ -83,7 +83,7 @@ libmme = static_library('mme', libcrypt_dep, libsctp_dep, libs1ap_dep, - libnas_dep, + libnas_eps_dep, libdiameter_s6a_dep, libgtp_dep], install : false) @@ -94,7 +94,7 @@ libmme_dep = declare_dependency( libcrypt_dep, libsctp_dep, libs1ap_dep, - libnas_dep, + libnas_eps_dep, libdiameter_s6a_dep, libgtp_dep]) diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 2871193b7..e067c58e0 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -25,7 +25,7 @@ #include "ogs-s1ap.h" #include "ogs-diameter-s6a.h" #include "ogs-gtp.h" -#include "ogs-nas.h" +#include "ogs-nas-eps.h" #include "ogs-app.h" /* S1AP */ diff --git a/src/mme/s1ap-sm.c b/src/mme/s1ap-sm.c index c0dd74576..a18a04f60 100644 --- a/src/mme/s1ap-sm.c +++ b/src/mme/s1ap-sm.c @@ -18,7 +18,7 @@ */ #include "ogs-gtp.h" -#include "ogs-nas.h" +#include "ogs-nas-eps.h" #include "s1ap-build.h" #include "s1ap-handler.h"