open5gs/lib/proto/types.h

934 lines
32 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#if !defined(OGS_PROTO_INSIDE) && !defined(OGS_PROTO_COMPILATION)
#error "This header cannot be included directly."
#endif
#ifndef OGS_PROTO_TYPES_H
#define OGS_PROTO_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define OGS_MAX_NUM_OF_SESS 4 /* Num of APN(Session) per UE */
#define OGS_MAX_NUM_OF_BEARER 4 /* Num of Bearer per Session */
#define OGS_BEARER_PER_UE 8 /* Num of Bearer per UE */
#define OGS_MAX_NUM_OF_PACKET_BUFFER 64 /* Num of PacketBuffer per UE */
/*
* The array of TLV messages is limited to 8.
* So, Flow(PDI.SDF_Filter) in PDR is limited to 8.
*
* However, the number of flow in bearer context seems to need more than 16.
*
* Therefore, the maximum number of flows of messages is defined as 8,
* and the maximum number of flows stored by the context is 16.
*/
#define OGS_MAX_NUM_OF_FLOW_IN_PDR 8
#define OGS_MAX_NUM_OF_FLOW_IN_GTP OGS_MAX_NUM_OF_FLOW_IN_PDR
#define OGS_MAX_NUM_OF_FLOW_IN_NAS OGS_MAX_NUM_OF_FLOW_IN_PDR
#define OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE OGS_MAX_NUM_OF_FLOW_IN_PDR
#define OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT OGS_MAX_NUM_OF_FLOW_IN_PDR
#define OGS_MAX_NUM_OF_FLOW_IN_BEARER 16
#define OGS_MAX_NUM_OF_GTPU_RESOURCE 4
#define OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI 8
#define OGS_PLMN_ID_LEN 3
#define OGS_MAX_PLMN_ID_BCD_LEN 6
#define OGS_CHRGCHARS_LEN 2
#define OGS_MSIN_LEN 5
#define OGS_BCD_TO_BUFFER_LEN(x) (((x)+1)/2)
#define OGS_MAX_IMSI_BCD_LEN 15
#define OGS_MAX_IMSI_LEN \
OGS_BCD_TO_BUFFER_LEN(OGS_MAX_IMSI_BCD_LEN)
#define OGS_MAX_IMEISV_BCD_LEN 16
#define OGS_MAX_IMEISV_LEN \
OGS_BCD_TO_BUFFER_LEN(OGS_MAX_IMEISV_BCD_LEN)
#define OGS_MAX_MSISDN_BCD_LEN 15
#define OGS_MAX_MSISDN_LEN \
OGS_BCD_TO_BUFFER_LEN(OGS_MAX_MSISDN_BCD_LEN)
#define OGS_MAX_NUM_OF_CELL_ID 16
#define OGS_MAX_NUM_OF_ENB_ID 16
#define OGS_MAX_NUM_OF_DNN 16
#define OGS_MAX_NUM_OF_APN OGS_MAX_NUM_OF_DNN
#define OGS_MAX_NUM_OF_HOSTNAME 16
#define OGS_MAX_DNN_LEN 100
#define OGS_MAX_APN_LEN OGS_MAX_DNN_LEN
#define OGS_MAX_PCO_LEN 251
#define OGS_MAX_EPCO_LEN 65535
#define OGS_MAX_FQDN_LEN 256
#define OGS_MAX_NUM_OF_ALGORITHM 8
#define OGS_MAX_NUM_OF_SERVED_GUMMEI 8 /* maxnoofRATs: 8 */
#define OGS_MAX_NUM_OF_SERVED_GUAMI 256 /* maxnoofServedGUAMIs: 256 */
#define OGS_MAX_NUM_OF_SUPPORTED_TA 256 /* maxnoofTACs: 256 */
/*
* <December 3, 2023>
* If I set it to 1024, the AMF crashes in the 'meson test -v registration'.
* So for now, I will use 512. Once I figure out the cause of this problem,
* I will try 1024.
*
* <December 4, 2023>
* After increasing the delay in test/app/5gc-init.c from 300ms to 500ms,
* the problem has been resolved. It seems that as the context memory increases,
* it takes time for the AMF execution to be completed."
*/
#define OGS_MAX_NUM_OF_SLICE_SUPPORT 1024 /* maxnoofSliceItems: 1024 */
#define OGS_MAX_NUM_OF_PLMN_PER_MME 32 /* maxnoofPLMNs(MME): 32 */
#define OGS_MAX_NUM_OF_PLMN 12 /* maxnoofPLMNs(AMF): 12 */
#define OGS_MAX_NUM_OF_BPLMN OGS_MAX_NUM_OF_PLMN
#define OGS_MAX_NUM_OF_TAI 16
#define OGS_MAX_NUM_OF_SLICE 8
#define OGS_NEXT_ID(__id, __min, __max) \
((__id) = ((__id) == (__max) ? (__min) : ((__id) + 1)))
#define OGS_COMPARE_ID(__id1, __id2, __max) \
((__id2) > (__id1) ? ((__id2) - (__id1) < ((__max)-1) ? -1 : 1) : \
(__id1) > (__id2) ? ((__id1) - (__id2) < ((__max)-1) ? 1 : -1) : 0)
#define OGS_TIME_TO_BCD(x) \
(((((x) % 10) << 4) & 0xf0) | (((x) / 10) & 0x0f))
#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0
#define OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED 0
#define OGS_ACCESS_TYPE_3GPP 1
#define OGS_ACCESS_TYPE_NON_3GPP 2
#define OGS_ACCESS_TYPE_BOTH_3GPP_AND_NON_3GPP 3
#define OGS_MAX_QOS_FLOW_ID 63
#define OGS_IMSI_STRING "imsi"
#define OGS_MSISDN_STRING "msisdn"
#define OGS_IMEISV_STRING "imeisv"
#define OGS_ACCESS_RESTRICTION_DATA_STRING "access_restriction_data"
#define OGS_SUBSCRIBER_STATUS_STRING "subscriber_status"
#define OGS_OPERATOR_DETERMINED_BARRING_STRING "operator_determined_barring"
#define OGS_NETWORK_ACCESS_MODE_STRING "network_access_mode"
#define OGS_SUBSCRIBED_RAU_TAU_TIMER_STRING "subscribed_rau_tau_timer"
#define OGS_SECURITY_STRING "security"
#define OGS_K_STRING "k"
#define OGS_OPC_STRING "opc"
#define OGS_OP_STRING "op"
#define OGS_AMF_STRING "amf"
#define OGS_RAND_STRING "rand"
#define OGS_SQN_STRING "sqn"
#define OGS_MME_HOST_STRING "mme_host"
#define OGS_MME_REALM_STRING "mme_realm"
#define OGS_MME_TIMESTAMP_STRING "mme_timestamp"
#define OGS_PURGE_FLAG_STRING "purge_flag"
#define OGS_AMBR_STRING "ambr"
#define OGS_DOWNLINK_STRING "downlink"
#define OGS_UPLINK_STRING "uplink"
#define OGS_VALUE_STRING "value"
#define OGS_UNIT_STRING "unit"
#define OGS_POLICY_STRING "policy"
#define OGS_SLICE_STRING "slice"
#define OGS_SST_STRING "sst"
#define OGS_SD_STRING "sd"
#define OGS_DEFAULT_INDICATOR_STRING "default_indicator"
#define OGS_SESSION_STRING "session"
#define OGS_NAME_STRING "name"
#define OGS_TYPE_STRING "type"
#define OGS_QOS_STRING "qos"
#define OGS_INDEX_STRING "index"
#define OGS_ARP_STRING "arp"
#define OGS_PRIORITY_LEVEL_STRING "priority_level"
#define OGS_PRE_EMPTION_CAPABILITY_STRING "pre_emption_capability"
#define OGS_PRE_EMPTION_VULNERABILITY_STRING "pre_emption_vulnerability"
#define OGS_PCC_RULE_STRING "pcc_rule"
#define OGS_MBR_STRING "mbr"
#define OGS_GBR_STRING "gbr"
#define OGS_FLOW_STRING "flow"
#define OGS_DIRECTION_STRING "direction"
#define OGS_DESCRIPTION_STRING "description"
#define OGS_SMF_STRING "smf"
#define OGS_IPV4_STRING "ipv4"
#define OGS_IPV6_STRING "ipv6"
#define OGS_UE_STRING "ue"
#define OGS_IPV4_FRAMED_ROUTES_STRING "ipv4_framed_routes"
#define OGS_IPV6_FRAMED_ROUTES_STRING "ipv6_framed_routes"
/************************************
* PLMN_ID Structure */
typedef struct ogs_plmn_id_s {
ED2(uint8_t mcc2:4;,
uint8_t mcc1:4;)
ED2(uint8_t mnc1:4;,
uint8_t mcc3:4;)
ED2(uint8_t mnc3:4;,
uint8_t mnc2:4;)
} __attribute__ ((packed)) ogs_plmn_id_t;
uint32_t ogs_plmn_id_hexdump(void *plmn_id);
uint16_t ogs_plmn_id_mcc(ogs_plmn_id_t *plmn_id);
uint16_t ogs_plmn_id_mnc(ogs_plmn_id_t *plmn_id);
uint16_t ogs_plmn_id_mnc_len(ogs_plmn_id_t *plmn_id);
void *ogs_plmn_id_build(ogs_plmn_id_t *plmn_id,
uint16_t mcc, uint16_t mnc, uint16_t mnc_len);
char *ogs_plmn_id_mcc_string(ogs_plmn_id_t *plmn_id);
char *ogs_plmn_id_mnc_string(ogs_plmn_id_t *plmn_id);
#define OGS_PLMNIDSTRLEN (sizeof(ogs_plmn_id_t)*2+1)
char *ogs_plmn_id_to_string(ogs_plmn_id_t *plmn_id, char *buf);
char *ogs_serving_network_name_from_plmn_id(ogs_plmn_id_t *plmn_id);
char *ogs_home_network_domain_from_plmn_id(ogs_plmn_id_t *plmn_id);
char *ogs_nrf_fqdn_from_plmn_id(ogs_plmn_id_t *plmn_id);
char *ogs_nssf_fqdn_from_plmn_id(ogs_plmn_id_t *plmn_id);
char *ogs_home_network_domain_from_fqdn(char *fqdn);
uint16_t ogs_plmn_id_mnc_from_fqdn(char *fqdn);
uint16_t ogs_plmn_id_mcc_from_fqdn(char *fqdn);
/*************************
* 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);
/************************************
* AMF_ID Structure */
typedef struct ogs_amf_id_s {
uint8_t region;
uint8_t set1;
ED2(uint8_t set2:2;,
uint8_t pointer:6;)
} __attribute__ ((packed)) ogs_amf_id_t;
typedef struct ogs_guami_s {
ogs_plmn_id_t plmn_id;
ogs_amf_id_t amf_id;
} ogs_guami_t;
uint32_t ogs_amf_id_hexdump(ogs_amf_id_t *amf_id);
ogs_amf_id_t *ogs_amf_id_from_string(ogs_amf_id_t *amf_id, const char *hex);
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id);
uint8_t ogs_amf_region_id(ogs_amf_id_t *amf_id);
uint16_t ogs_amf_set_id(ogs_amf_id_t *amf_id);
uint8_t ogs_amf_pointer(ogs_amf_id_t *amf_id);
ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
uint8_t region, uint16_t set, uint8_t pointer);
/************************************
* 9.11.3.4 5GS mobile identity
* - Protection Scheme */
#define OGS_PROTECTION_SCHEME_NULL 0
#define OGS_PROTECTION_SCHEME_PROFILE_A 1
#define OGS_PROTECTION_SCHEME_PROFILE_B 2
/************************************
* SUPI/GPSI */
#define OGS_ID_SUPI_TYPE_IMSI "imsi"
#define OGS_ID_GPSI_TYPE_MSISDN "msisdn"
#define OGS_ID_SUPI_TYPE_IMEISV "imeisv"
char *ogs_id_get_type(char *str);
char *ogs_id_get_value(char *str);
/************************************
* TAI Structure */
typedef struct ogs_eps_tai_s {
ogs_plmn_id_t plmn_id;
uint16_t tac;
} __attribute__ ((packed)) ogs_eps_tai_t;
typedef struct ogs_5gs_tai_s {
ogs_plmn_id_t plmn_id;
ogs_uint24_t tac;
} __attribute__ ((packed)) ogs_5gs_tai_t;
typedef struct ogs_e_cgi_s {
ogs_plmn_id_t plmn_id;
uint32_t cell_id; /* 28 bit */
} __attribute__ ((packed)) ogs_e_cgi_t;
typedef struct ogs_nr_cgi_s {
ogs_plmn_id_t plmn_id;
uint64_t cell_id; /* 36 bit */
} __attribute__ ((packed)) ogs_nr_cgi_t;
/************************************
* S-NSSAI Structure */
#define OGS_S_NSSAI_NO_SD_VALUE 0xffffff
typedef struct ogs_s_nssai_s {
uint8_t sst;
ogs_uint24_t sd;
} __attribute__ ((packed)) ogs_s_nssai_t;
char *ogs_s_nssai_sd_to_string(ogs_uint24_t sd);
ogs_uint24_t ogs_s_nssai_sd_from_string(const char *hex);
/**************************************************
* Common Structure
* S1AP : 9.2.2.1 Transport Layer Address, See 36.414
* GTP : 8.22 Fully Qualified TEID (F-TEID) */
#define OGS_IPV4_LEN 4
#define OGS_IPV6_LEN 16
#define OGS_IPV6_DEFAULT_PREFIX_LEN 64
#define OGS_IPV6_128_PREFIX_LEN 128
#define OGS_IPV4V6_LEN 20
typedef struct ogs_ip_s {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
uint32_t len;
ED3(uint8_t ipv4:1;,
uint8_t ipv6:1;,
uint8_t reserved:6;)
} ogs_ip_t;
int ogs_ip_to_sockaddr(ogs_ip_t *ip, uint16_t port, ogs_sockaddr_t **list);
int ogs_sockaddr_to_ip(
ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6, ogs_ip_t *ip);
char *ogs_ipv4_to_string(uint32_t addr);
char *ogs_ipv6addr_to_string(uint8_t *addr6);
char *ogs_ipv6prefix_to_string(uint8_t *addr6, uint8_t prefixlen);
int ogs_ipv4_from_string(uint32_t *addr, char *string);
int ogs_ipv6addr_from_string(uint8_t *addr6, char *string);
int ogs_ipv6prefix_from_string(
uint8_t *addr6, uint8_t *prefixlen, char *string);
/**************************************************
* GTPv1-C: TS 29.060 7.7.27 End User Address (EUA) */
#define OGS_PDP_EUA_ORG_ETSI 0
#define OGS_PDP_EUA_ORG_IETF 1
#define OGS_PDP_EUA_ETSI_PPP 1
#define OGS_PDP_EUA_IETF_IPV4 0x21
#define OGS_PDP_EUA_IETF_IPV6 0x57
#define OGS_PDP_EUA_IETF_IPV4V6 0x8D
typedef struct ogs_eua_s {
ED2(uint8_t spare:4;,
uint8_t organization:4;)
uint8_t type;
union {
/* PDU_SESSION_TYPE_IPV4 */
uint32_t addr;
/* PDU_SESSION_TYPE_IPV6 */
uint8_t addr6[OGS_IPV6_LEN];
/* PDU_SESSION_TYPE_IPV4V6 */
struct {
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
} __attribute__ ((packed)) both;
};
} __attribute__ ((packed)) ogs_eua_t;
/**************************************************
* GTPv2-C: TS 29.274 8.14 PDN Address Allocation (PAA) */
#define OGS_PAA_IPV4_LEN 5
#define OGS_PAA_IPV6_LEN 18
#define OGS_PAA_IPV4V6_LEN 22
typedef struct ogs_paa_s {
ED2(uint8_t spare:5;,
/* 8.34 PDN Type */
#define OGS_PDU_SESSION_TYPE_IS_VALID(x) \
((x) == OGS_PDU_SESSION_TYPE_IPV4 || \
(x) == OGS_PDU_SESSION_TYPE_IPV6 || \
(x) == OGS_PDU_SESSION_TYPE_IPV4V6) \
uint8_t session_type:3;)
union {
/* PDU_SESSION_TYPE_IPV4 */
uint32_t addr;
/* PDU_SESSION_TYPE_IPV6 */
struct {
/* the IPv6 Prefix Length */
uint8_t len;
/* IPv6 Prefix and Interface Identifier */
uint8_t addr6[OGS_IPV6_LEN];
};
/* PDU_SESSION_TYPE_IPV4V6 */
struct {
struct {
/* the IPv6 Prefix Length */
uint8_t len;
/* IPv6 Prefix and Interface Identifier */
uint8_t addr6[OGS_IPV6_LEN];
};
uint32_t addr;
} __attribute__ ((packed)) both;
};
} __attribute__ ((packed)) ogs_paa_t;
#define MAX_BIT_RATE 10000000000UL
typedef struct ogs_bitrate_s {
uint64_t downlink; /* bits per seconds */
uint64_t uplink; /* bits per seconds */
} ogs_bitrate_t;
int ogs_check_br_conf(ogs_bitrate_t *br);
/**********************************
* QoS Structure */
typedef struct ogs_qos_s {
#define OGS_QOS_INDEX_1 1
#define OGS_QOS_INDEX_2 2
#define OGS_QOS_INDEX_5 5
uint8_t index;
struct {
/* Values 1 to 8 should only be assigned for services that are
* authorized to receive prioritized treatment within an operator domain.
* Values 9 to 15 may be assigned to resources that are authorized
* by the home network and thus applicable when a UE is roaming. */
uint8_t priority_level;
/*
* Ch 7.3.40 Allocation-Retenion-Proirty in TS 29.272 V15.9.0
*
* If the Pre-emption-Capability AVP is not present in the
* Allocation-Retention-Priority AVP, the default value shall be
* PRE-EMPTION_CAPABILITY_DISABLED (1).
*
* If the Pre-emption-Vulnerability AVP is not present in the
* Allocation-Retention-Priority AVP, the default value shall be
* PRE-EMPTION_VULNERABILITY_ENABLED (0).
*
* However, to easily set up VoLTE service,
* enable Pre-emption Capability/Vulnerablility
* in Default Bearer
*/
#define OGS_EPC_PRE_EMPTION_DISABLED 1
#define OGS_EPC_PRE_EMPTION_ENABLED 0
#define OGS_5GC_PRE_EMPTION_DISABLED 1
#define OGS_5GC_PRE_EMPTION_ENABLED 2
uint8_t pre_emption_capability;
uint8_t pre_emption_vulnerability;
} arp;
ogs_bitrate_t mbr; /* Maxmimum Bit Rate (MBR) */
ogs_bitrate_t gbr; /* Guaranteed Bit Rate (GBR) */
} ogs_qos_t;
int ogs_check_qos_conf(ogs_qos_t *qos);
/**********************************
* Flow Structure */
#define OGS_FLOW_DOWNLINK_ONLY 1
#define OGS_FLOW_UPLINK_ONLY 2
typedef struct ogs_flow_s {
uint8_t direction;
char *description;
} ogs_flow_t;
#define OGS_FLOW_FREE(__fLOW) \
do { \
if ((__fLOW)->description) { \
ogs_free((__fLOW)->description); \
} \
else \
ogs_assert_if_reached(); \
} while(0)
/**********************************
* PCC Rule Structure */
typedef struct ogs_pcc_rule_s {
#define OGS_PCC_RULE_TYPE_INSTALL 1
#define OGS_PCC_RULE_TYPE_REMOVE 2
uint8_t type;
char *id; /* 5GC */
char *name; /* EPC */
ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE];
int num_of_flow;
int flow_status;
uint32_t precedence;
ogs_qos_t qos;
} ogs_pcc_rule_t;
#define OGS_STORE_PCC_RULE(__dST, __sRC) \
do { \
int __iNDEX; \
ogs_assert((__sRC) != NULL); \
ogs_assert((__dST) != NULL); \
OGS_PCC_RULE_FREE(__dST); \
(__dST)->type = (__sRC)->type; \
if ((__sRC)->name) { \
(__dST)->name = ogs_strdup((__sRC)->name); \
ogs_assert((__dST)->name); \
} \
if ((__sRC)->id) { \
(__dST)->id = ogs_strdup((__sRC)->id); \
ogs_assert((__dST)->id); \
} \
for (__iNDEX = 0; __iNDEX < (__sRC)->num_of_flow; __iNDEX++) { \
(__dST)->flow[__iNDEX].direction = \
(__sRC)->flow[__iNDEX].direction; \
(__dST)->flow[__iNDEX].description = \
ogs_strdup((__sRC)->flow[__iNDEX].description); \
ogs_assert((__dST)->flow[__iNDEX].description); \
} \
(__dST)->num_of_flow = (__sRC)->num_of_flow; \
(__dST)->flow_status = (__sRC)->flow_status; \
(__dST)->precedence = (__sRC)->precedence; \
memcpy(&(__dST)->qos, &(__sRC)->qos, sizeof(ogs_qos_t)); \
} while(0)
#define OGS_PCC_RULE_FREE(__pCCrULE) \
do { \
int __pCCrULE_iNDEX; \
ogs_assert((__pCCrULE) != NULL); \
if ((__pCCrULE)->id) \
ogs_free((__pCCrULE)->id); \
if ((__pCCrULE)->name) \
ogs_free((__pCCrULE)->name); \
for (__pCCrULE_iNDEX = 0; \
__pCCrULE_iNDEX < (__pCCrULE)->num_of_flow; __pCCrULE_iNDEX++) { \
OGS_FLOW_FREE(&((__pCCrULE)->flow[__pCCrULE_iNDEX])); \
} \
memset((__pCCrULE), 0, sizeof(ogs_pcc_rule_t)); \
} while(0)
/**********************************
* PDN Structure */
typedef struct ogs_session_s {
char *name;
uint32_t context_identifier; /* EPC */
bool default_dnn_indicator; /* 5GC */
uint8_t charging_characteristics[OGS_CHRGCHARS_LEN];
bool charging_characteristics_presence;
#define OGS_PDU_SESSION_TYPE_IPV4 1
#define OGS_PDU_SESSION_TYPE_IPV6 2
#define OGS_PDU_SESSION_TYPE_IPV4V6 3
#define OGS_PDU_SESSION_TYPE_UNSTRUCTURED 4
#define OGS_PDU_SESSION_TYPE_ETHERNET 5
#define OGS_PDU_SESSION_TYPE_TO_DIAMETER(x) ((x)-1)
#define OGS_PDU_SESSION_TYPE_FROM_DIAMETER(x) ((x)+1)
uint8_t session_type;
#define OGS_SSC_MODE_1 1
#define OGS_SSC_MODE_2 2
#define OGS_SSC_MODE_3 3
uint8_t ssc_mode;
ogs_qos_t qos;
ogs_bitrate_t ambr; /* APN-AMBR */
ogs_paa_t paa;
ogs_ip_t ue_ip;
char **ipv4_framed_routes;
char **ipv6_framed_routes;
ogs_ip_t smf_ip;
} ogs_session_t;
int ogs_fqdn_build(char *dst, char *src, int len);
int ogs_fqdn_parse(char *dst, char *src, int len);
/**************************************************
* Protocol Configuration Options Structure
* 8.13 Protocol Configuration Options (PCO)
* 10.5.6.3 Protocol configuration options in 3GPP TS 24.008
* RFC 3232 [103]
* RFC 1661 [102] */
#define OGS_PCO_PPP_FOR_USE_WITH_IP_PDP_TYPE_OR_IP_PDN_TYPE 0
#define OGS_PCO_ID_INTERNET_PROTOCOL_CONTROL_PROTOCOL 0x8021
#define OGS_PCO_ID_PASSWORD_AUTHENTICATION_PROTOCOL 0xc023
#define OGS_PCO_ID_CHALLENGE_HANDSHAKE_AUTHENTICATION_PROTOCOL 0xc223
#define OGS_PCO_ID_P_CSCF_IPV6_ADDRESS_REQUEST 0x0001
#define OGS_PCO_ID_DNS_SERVER_IPV6_ADDRESS_REQUEST 0x0003
#define OGS_PCO_ID_MS_SUPPORTS_BCM 0x0005
#define OGS_PCO_ID_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING 0x000a
#define OGS_PCO_ID_P_CSCF_IPV4_ADDRESS_REQUEST 0x000c
#define OGS_PCO_ID_DNS_SERVER_IPV4_ADDRESS_REQUEST 0x000d
#define OGS_PCO_ID_IPV4_LINK_MTU_REQUEST 0x0010
#define OGS_PCO_ID_MS_SUPPORT_LOCAL_ADDR_TFT_INDICATOR 0x0011
#define OGS_PCO_ID_P_CSCF_RE_SELECTION_SUPPORT 0x0012
enum ogs_pco_ipcp_options {
OGS_IPCP_OPT_IPADDR = 3,
OGS_IPCP_OPT_PRIMARY_DNS = 129,
OGS_IPCP_OPT_SECONDARY_DNS = 131,
};
typedef struct ogs_pco_ipcp_options_s {
uint8_t type;
uint8_t len;
uint32_t addr;
} __attribute__ ((packed)) ogs_pco_ipcp_options_t;
#define OGS_PCO_MAX_NUM_OF_IPCP_OPTIONS 4
typedef struct ogs_pco_ipcp_s {
uint8_t code;
uint8_t identifier;
uint16_t len;
ogs_pco_ipcp_options_t options[OGS_PCO_MAX_NUM_OF_IPCP_OPTIONS];
} __attribute__ ((packed)) ogs_pco_ipcp_t;
typedef struct ogs_pco_pap_s {
uint8_t code;
uint8_t identifier;
uint16_t len;
uint8_t welcome_len;
char welcome[255];
} __attribute__ ((packed)) ogs_pco_pap_t;
typedef struct ogs_pco_chap_s {
uint8_t code;
uint8_t identifier;
uint16_t len;
} __attribute__ ((packed)) ogs_pco_chap_t;
typedef struct ogs_pco_id_s {
uint16_t id;
uint8_t len;
void *data;
} ogs_pco_id_t;
#define OGS_MAX_NUM_OF_PROTOCOL_OR_CONTAINER_ID 16
typedef struct ogs_pco_s {
ED3(uint8_t ext:1;,
uint8_t spare:4;,
uint8_t configuration_protocol:3;)
uint8_t num_of_id;
ogs_pco_id_t ids[OGS_MAX_NUM_OF_PROTOCOL_OR_CONTAINER_ID];
} ogs_pco_t;
int ogs_pco_parse(ogs_pco_t *pco, unsigned char *data, int data_len);
int ogs_pco_build(unsigned char *data, int data_len, ogs_pco_t *pco);
/*
* PFCP Specification
*
* TS29.244, Ch 8.2.82 User Plane IP Resource Information
*
* The following flags are coded within Octet 5:
* - Bit 1 V4: If this bit is set to "1", then the IPv4 address field
* shall be present, otherwise the IPv4 address field shall not be present.
* - Bit 2 V6: If this bit is set to "1", then the IPv6 address field
* shall be present, otherwise the IPv6 address field shall not be present.
* - Bit 3-5 TEID Range Indication (TEIDRI): the value of this field
* indicates the number of bits in the most significant octet of a TEID
* that are used to partition the TEID range,
* e.g. if this field is set to "4", then the first 4 bits in the TEID
* are used to partition the TEID range.
* - Bit 6 Associated Network Instance (ASSONI): if this bit is set to "1",
* then the Network Instance field shall be present, otherwise the Network
* Instance field shall not be present.
* - Bit 7 Associated Source Interface (ASSOSI): if this bit is set to "1",
* then the Source Interface field shall be present,
* otherwise the Source Interface field shall not be present.
* - Bit 8: Spare, for future use and set to 0.
*
* At least one of the V4 and V6 flags shall be set to "1",
* and both may be set to "1".
*
* If both the ASSONI and ASSOSI flags are set to "0", this shall indicate
* that the User Plane IP Resource Information provided can be used
* by CP function for any Network Instance and any Source Interface
* of GTP-U user plane in the UP function. Octet 6 (TEID Range) shall be
* present if the TEID Range Indication is not set to zero and
* shall contain a value of the bits which are used to partition the TEID range.
* E.g. if the TEID Range Indication is set to "4", then Octet 6 shall be
* one of values between 0 and 15. When TEID Range Indication is set to zero,
* the Octet 6 shall not be present, the TEID is not partitioned,
* i.e. all TEID values are available for use by the CP function.
*
* Octets "m to (m+3)" and/or "p to (p+15)" (IPv4 address / IPv6 address fields)
* , if present, shall contain the respective IP address values.
*
* Octets "k to l", if present, shall contain a Network Instance value
* as encoded in octet "5 to n+4" of the Figure 8.2.4-1 in clause 8.2.4,
* identifying a Network Instance with which the IP address or TEID Range
* is associated.
*
* Octet r, if present, shall contain a Source Interface value as encoded
* in octet 5 of the Figure 8.2.2-1 in clause 8.2.2,
* identifying the Source Interface with which the IP address or TEID Range
* is associated.
*/
/* Flags(1) + TEID Range(1) + IPV4(4) + IPV6(16) + Source Interface(1) = 23 */
#define OGS_MAX_USER_PLANE_IP_RESOURCE_INFO_LEN \
(23 + (OGS_MAX_APN_LEN+1))
typedef struct ogs_user_plane_ip_resource_info_s {
union {
struct {
ED6(uint8_t spare:1;,
uint8_t assosi:1;,
uint8_t assoni:1;,
uint8_t teidri:3;,
uint8_t v6:1;,
uint8_t v4:1;)
};
uint8_t flags;
};
/*
* OGS_PFCP-GTPU-TEID = INDEX | TEID_RANGE
* INDEX = OGS_PFCP-GTPU-TEID & ~TEID_RANGE
*/
#define OGS_PFCP_GTPU_TEID_TO_INDEX(__tEID, __iND, __rANGE) \
(__tEID & ~(__rANGE << (32 - __iND)))
#define OGS_PFCP_GTPU_INDEX_TO_TEID(__iNDEX, __iND, __rANGE) \
(__iNDEX | (__rANGE << (32 - __iND)))
uint8_t teid_range;
uint32_t addr;
uint8_t addr6[OGS_IPV6_LEN];
char network_instance[OGS_MAX_APN_LEN+1];
uint8_t source_interface;
} __attribute__ ((packed)) ogs_user_plane_ip_resource_info_t;
int ogs_sockaddr_to_user_plane_ip_resource_info(
ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6,
ogs_user_plane_ip_resource_info_t *info);
int ogs_user_plane_ip_resource_info_to_sockaddr(
ogs_user_plane_ip_resource_info_t *info,
ogs_sockaddr_t **addr, ogs_sockaddr_t **addr6);
typedef struct ogs_slice_data_s {
ogs_s_nssai_t s_nssai;
bool default_indicator;
uint32_t context_identifier; /* EPC for checking default APN */
#define OGS_ALL_APN_CONFIGURATIONS_INCLUDED 0
#define OGS_MODIFIED_ADDED_APN_CONFIGURATIONS_INCLUDED 1
uint32_t all_apn_config_inc;
int num_of_session;
ogs_session_t session[OGS_MAX_NUM_OF_SESS];
} ogs_slice_data_t;
ogs_slice_data_t *ogs_slice_find_by_s_nssai(
ogs_slice_data_t *slice_data, int num_of_slice_data,
ogs_s_nssai_t *s_nssai);
typedef struct ogs_subscription_data_s {
#define OGS_ACCESS_RESTRICTION_UTRAN_NOT_ALLOWED (1)
#define OGS_ACCESS_RESTRICTION_GERAN_NOT_ALLOWED (1<<1)
#define OGS_ACCESS_RESTRICTION_GAN_NOT_ALLOWED (1<<2)
#define OGS_ACCESS_RESTRICTION_I_HSPA_EVOLUTION_NOT_ALLOWED (1<<3)
#define OGS_ACCESS_RESTRICTION_WB_E_UTRAN_NOT_ALLOWED (1<<4)
#define OGS_ACCESS_RESTRICTION_HO_TO_NON_3GPP_ACCESS_NOT_ALLOWED (1<<5)
#define OGS_ACCESS_RESTRICTION_NB_IOT_NOT_ALLOWED (1<<6)
uint32_t access_restriction_data;
#define OGS_SUBSCRIBER_STATUS_SERVICE_GRANTED 0
#define OGS_SUBSCRIBER_STATUS_OPERATOR_DETERMINED_BARRING 1
uint32_t subscriber_status;
#define OGS_OP_DET_BARRING_ALL_PS_BARRED (1<<0)
#define OGS_OP_DET_BARRING_ROAM_ACC_HPLMN_AP_BARRED (1<<1)
#define OGS_OP_DET_BARRING_ROAM_ACC_VPLMN_AP_BARRED (1<<2)
#define OGS_OP_DET_BARRING_ALL_OUT_CALLS (1<<3)
#define OGS_OP_DET_BARRING_ALL_OUT_INT_CALLS (1<<4)
#define OGS_OP_DET_BARRING_ALL_OUT_INT_CALLS_EXCL_HPLMN_COUNTRY (1<<5)
#define OGS_OP_DET_BARRING_ALL_OUT_INTERZONE_CALLS (1<<6)
#define OGS_OP_DET_BARRING_ALL_OUT_INTERZONE_CALLS_EXCL_HPLMN_COUNTRY (1<<7)
#define OGS_OPD_ETEBARRING_OUT_INT_CALLS_EXCL_EXCL_HPLMN_COUNTRY_AND_INTERZONE_CALLS (1<<8)
uint32_t operator_determined_barring; /* 3GPP TS 29.272 7.3.30 */
#define OGS_NETWORK_ACCESS_MODE_PACKET_AND_CIRCUIT 0
#define OGS_NETWORK_ACCESS_MODE_RESERVED 1
#define OGS_NETWORK_ACCESS_MODE_ONLY_PACKET 2
uint32_t network_access_mode;
ogs_bitrate_t ambr; /* UE-AMBR */
#define OGS_RAU_TAU_DEFAULT_TIME (12*60) /* 12 min */
uint32_t subscribed_rau_tau_timer; /* unit : seconds */
int num_of_slice;
ogs_slice_data_t slice[OGS_MAX_NUM_OF_SLICE];
char *imsi;
#define OGS_MAX_NUM_OF_MSISDN 2
int num_of_msisdn;
struct {
uint8_t buf[OGS_MAX_MSISDN_LEN];
int len;
char bcd[OGS_MAX_MSISDN_BCD_LEN+1];
} msisdn[OGS_MAX_NUM_OF_MSISDN];
char *mme_host;
char *mme_realm;
bool purge_flag;
} ogs_subscription_data_t;
void ogs_subscription_data_free(ogs_subscription_data_t *subscription_data);
typedef struct ogs_session_data_s {
ogs_session_t session;
#define OGS_MAX_NUM_OF_PCC_RULE 8 /* Num of PCC Rule */
ogs_pcc_rule_t pcc_rule[OGS_MAX_NUM_OF_PCC_RULE];
int num_of_pcc_rule;
} ogs_session_data_t;
#define OGS_STORE_SESSION_DATA(__dST, __sRC) \
do { \
int rv, j; \
ogs_assert((__dST) != NULL); \
ogs_assert((__sRC) != NULL); \
OGS_SESSION_DATA_FREE(__dST); \
if ((__sRC)->session.name) { \
(__dST)->session.name = ogs_strdup((__sRC)->session.name); \
ogs_assert((__dST)->session.name); \
} \
(__dST)->session.session_type = (__sRC)->session.session_type; \
memcpy(&(__dST)->session.ambr, &(__sRC)->session.ambr, \
sizeof((__dST)->session.ambr)); \
memcpy(&(__dST)->session.qos, &(__sRC)->session.qos, \
sizeof((__dST)->session.qos)); \
(__dST)->num_of_pcc_rule = (__sRC)->num_of_pcc_rule; \
for (j = 0; j < (__dST)->num_of_pcc_rule; j++) { \
rv = ogs_check_qos_conf(&(__sRC)->pcc_rule[j].qos); \
ogs_assert(rv == OGS_OK); \
OGS_STORE_PCC_RULE(&(__dST)->pcc_rule[j], &(__sRC)->pcc_rule[j]); \
} \
} while(0)
#define OGS_SESSION_DATA_FREE(__sESSdATA) \
do { \
int i; \
ogs_assert((__sESSdATA) != NULL); \
if ((__sESSdATA)->session.name) \
ogs_free((__sESSdATA)->session.name); \
for (i = 0; i < (__sESSdATA)->num_of_pcc_rule; i++) \
OGS_PCC_RULE_FREE(&(__sESSdATA)->pcc_rule[i]); \
memset((__sESSdATA), 0, sizeof(ogs_session_data_t)); \
} while(0)
typedef struct ogs_media_sub_component_s {
uint32_t flow_number;
/*
* TS29.214
* 5.3.12 Flow-Usage AVP
* NO_INFORMATION(0)
* RTCP(1)
* AF_SIGNALLING(2)
*
* TS29.514
* 5.6.3.14 Enumeration: FlowUsage
* NO_INFO : 1
* RTCP : 2
* AF_SIGNALLING : 3
*
* EPC and 5GC have different values for FlowUsage
* At this point, we will use the 5GC value.
*/
#define OGS_FLOW_USAGE_NO_INFO 1
#define OGS_FLOW_USAGE_RTCP 2
#define OGS_FLOW_USAGE_AF_SIGNALLING 3
uint32_t flow_usage;
ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT];
int num_of_flow;
} ogs_media_sub_component_t;
typedef struct ogs_media_component_s {
uint32_t media_component_number;
uint32_t media_type;
uint64_t max_requested_bandwidth_dl;
uint64_t max_requested_bandwidth_ul;
uint64_t min_requested_bandwidth_dl;
uint64_t min_requested_bandwidth_ul;
uint64_t rr_bandwidth;
uint64_t rs_bandwidth;
int flow_status;
#define OGS_MAX_NUM_OF_MEDIA_SUB_COMPONENT 8
ogs_media_sub_component_t sub[OGS_MAX_NUM_OF_MEDIA_SUB_COMPONENT];
int num_of_sub;
} ogs_media_component_t;
typedef struct ogs_ims_data_s {
int num_of_msisdn;
struct {
uint8_t buf[OGS_MAX_MSISDN_LEN];
int len;
char bcd[OGS_MAX_MSISDN_BCD_LEN+1];
} msisdn[OGS_MAX_NUM_OF_MSISDN];
#define OGS_MAX_NUM_OF_MEDIA_COMPONENT 16
ogs_media_component_t media_component[OGS_MAX_NUM_OF_MEDIA_COMPONENT];
int num_of_media_component;
} ogs_ims_data_t;
void ogs_ims_data_free(ogs_ims_data_t *ims_data);
int ogs_pcc_rule_num_of_flow_equal_to_media(
ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component);
int ogs_pcc_rule_install_flow_from_media(
ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component);
int ogs_pcc_rule_update_qos_from_media(
ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component);
typedef struct ogs_datum_s {
unsigned char *data;
unsigned int size;
} ogs_datum_t;
typedef struct ogs_port_s {
bool presence;
uint16_t port;
} ogs_port_t;
#ifdef __cplusplus
}
#endif
#endif /* OGS_PROTO_TYPES_H */