mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-23 07:41:57 +00:00
Merge branch 'main' into home-routed
This commit is contained in:
219
lib/dbi/ims.c
219
lib/dbi/ims.c
@@ -120,7 +120,8 @@ int ogs_dbi_ims_data(char *supi, ogs_ims_data_t *ims_data)
|
||||
bson_error_t error;
|
||||
const bson_t *document;
|
||||
bson_iter_t iter;
|
||||
bson_iter_t child1_iter;
|
||||
bson_iter_t child1_iter, child2_iter, child3_iter, child4_iter, child5_iter;
|
||||
bson_iter_t child6_iter, child7_iter, child8_iter, child9_iter;
|
||||
const char *utf8 = NULL;
|
||||
uint32_t length = 0;
|
||||
|
||||
@@ -190,6 +191,222 @@ int ogs_dbi_ims_data(char *supi, ogs_ims_data_t *ims_data)
|
||||
}
|
||||
}
|
||||
ims_data->num_of_msisdn = msisdn_index;
|
||||
} else if (!strcmp(key, "ifc") &&
|
||||
BSON_ITER_HOLDS_ARRAY(&iter)) {
|
||||
int ifc_index = 0;
|
||||
bson_iter_recurse(&iter, &child2_iter);
|
||||
while (bson_iter_next(&child2_iter)) {
|
||||
ogs_assert(ifc_index < OGS_MAX_NUM_OF_IFC);
|
||||
bson_iter_recurse(&child2_iter, &child3_iter);
|
||||
while (bson_iter_next(&child3_iter)) {
|
||||
const char *child3_key = bson_iter_key(&child3_iter);
|
||||
if (!strcmp(child3_key, "priority") &&
|
||||
BSON_ITER_HOLDS_INT32(&child3_iter)) {
|
||||
ims_data->ifc[ifc_index].priority =
|
||||
bson_iter_int32(&child3_iter);
|
||||
} else if (!strcmp(child3_key, "application_server") &&
|
||||
BSON_ITER_HOLDS_DOCUMENT(&child3_iter)) {
|
||||
bson_iter_recurse(&child3_iter, &child4_iter);
|
||||
while (bson_iter_next(&child4_iter)) {
|
||||
const char *child4_key =
|
||||
bson_iter_key(&child4_iter);
|
||||
if (!strcmp(child4_key, "server_name") &&
|
||||
BSON_ITER_HOLDS_UTF8(&child4_iter)) {
|
||||
utf8 = bson_iter_utf8(&child4_iter, &length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.application_server.server_name =
|
||||
ogs_strndup(utf8, length);
|
||||
} else if (!strcmp(child4_key, "default_handling")
|
||||
&& BSON_ITER_HOLDS_INT32(&child4_iter)) {
|
||||
ims_data->ifc[ifc_index]
|
||||
.application_server.default_handling =
|
||||
bson_iter_int32(&child4_iter);
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(child3_key, "trigger_point") &&
|
||||
BSON_ITER_HOLDS_DOCUMENT(&child3_iter)) {
|
||||
bson_iter_recurse(&child3_iter, &child5_iter);
|
||||
while (bson_iter_next(&child5_iter)) {
|
||||
const char *child5_key =
|
||||
bson_iter_key(&child5_iter);
|
||||
if (!strcmp(child5_key, "condition_type_cnf") &&
|
||||
BSON_ITER_HOLDS_INT32(&child5_iter)) {
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point.condition_type_cnf =
|
||||
bson_iter_int32(&child5_iter);
|
||||
} else if (!strcmp(child5_key, "spt") &&
|
||||
BSON_ITER_HOLDS_ARRAY(&child5_iter)) {
|
||||
int spt_index = 0;
|
||||
bson_iter_recurse(&child5_iter, &child6_iter);
|
||||
while (bson_iter_next(&child6_iter)) {
|
||||
ogs_assert(spt_index < OGS_MAX_NUM_OF_SPT);
|
||||
bson_iter_recurse(&child6_iter,
|
||||
&child7_iter);
|
||||
while (bson_iter_next(&child7_iter)) {
|
||||
const char *child7_key =
|
||||
bson_iter_key(&child7_iter);
|
||||
if (!strcmp(child7_key,
|
||||
"condition_negated") &&
|
||||
BSON_ITER_HOLDS_INT32(
|
||||
&child7_iter)) {
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.condition_negated =
|
||||
bson_iter_int32(
|
||||
&child7_iter);
|
||||
} else if (!strcmp(child7_key, "group")
|
||||
&& BSON_ITER_HOLDS_INT32(
|
||||
&child7_iter)) {
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.group = bson_iter_int32(
|
||||
&child7_iter);
|
||||
} else if (!strcmp(child7_key,
|
||||
"method") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child7_iter)) {
|
||||
utf8 = bson_iter_utf8(&child7_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.method =
|
||||
ogs_strndup(utf8, length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.type = OGS_SPT_HAS_METHOD;
|
||||
} else if (!strcmp(child7_key,
|
||||
"session_case") &&
|
||||
BSON_ITER_HOLDS_INT32(
|
||||
&child7_iter)) {
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.session_case =
|
||||
bson_iter_int32(
|
||||
&child7_iter);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.type =
|
||||
OGS_SPT_HAS_SESSION_CASE;
|
||||
} else if (!strcmp(child7_key,
|
||||
"sip_header") &&
|
||||
BSON_ITER_HOLDS_DOCUMENT(
|
||||
&child7_iter)) {
|
||||
bson_iter_recurse(&child7_iter,
|
||||
&child8_iter);
|
||||
while (bson_iter_next(
|
||||
&child8_iter)) {
|
||||
const char *child8_key =
|
||||
bson_iter_key(
|
||||
&child8_iter);
|
||||
if (!strcmp(child8_key,
|
||||
"header") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child8_iter)) {
|
||||
utf8 = bson_iter_utf8(
|
||||
&child8_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.header =
|
||||
ogs_strndup(utf8,
|
||||
length);
|
||||
} else if (!strcmp(child8_key,
|
||||
"content") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child8_iter)) {
|
||||
utf8 = bson_iter_utf8(
|
||||
&child8_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.header_content =
|
||||
ogs_strndup(utf8,
|
||||
length);
|
||||
}
|
||||
}
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.type = OGS_SPT_HAS_SIP_HEADER;
|
||||
} else if (!strcmp(child7_key,
|
||||
"sdp_line") &&
|
||||
BSON_ITER_HOLDS_DOCUMENT(
|
||||
&child7_iter)) {
|
||||
bson_iter_recurse(&child7_iter,
|
||||
&child9_iter);
|
||||
while (bson_iter_next(
|
||||
&child9_iter)) {
|
||||
const char *child9_key =
|
||||
bson_iter_key(
|
||||
&child9_iter);
|
||||
if (!strcmp(child9_key,
|
||||
"line") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child9_iter)) {
|
||||
utf8 = bson_iter_utf8(
|
||||
&child9_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.sdp_line =
|
||||
ogs_strndup(utf8,
|
||||
length);
|
||||
} else if (!strcmp(child9_key,
|
||||
"content") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child9_iter)) {
|
||||
utf8 = bson_iter_utf8(
|
||||
&child9_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.sdp_line_content =
|
||||
ogs_strndup(utf8,
|
||||
length);
|
||||
}
|
||||
}
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.type = OGS_SPT_HAS_SDP_LINE;
|
||||
} else if (!strcmp(child7_key,
|
||||
"request_uri") &&
|
||||
BSON_ITER_HOLDS_UTF8(
|
||||
&child7_iter)) {
|
||||
utf8 = bson_iter_utf8(&child7_iter,
|
||||
&length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.request_uri =
|
||||
ogs_strndup(utf8, length);
|
||||
ims_data->ifc[ifc_index]
|
||||
.trigger_point
|
||||
.spt[spt_index]
|
||||
.type = OGS_SPT_HAS_REQUEST_URI;
|
||||
}
|
||||
}
|
||||
spt_index++;
|
||||
}
|
||||
ims_data->ifc->trigger_point.num_of_spt =
|
||||
spt_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ifc_index++;
|
||||
}
|
||||
ims_data->num_of_ifc = ifc_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -92,6 +92,10 @@ struct dict_object *ogs_diam_s6a_software_version = NULL;
|
||||
struct dict_object *ogs_diam_s6a_msisdn = NULL;
|
||||
struct dict_object *ogs_diam_s6a_a_msisdn = NULL;
|
||||
|
||||
struct dict_object *ogs_diam_s6a_supported_features = NULL;
|
||||
struct dict_object *ogs_diam_s6a_feature_list_id = NULL;
|
||||
struct dict_object *ogs_diam_s6a_feature_list = NULL;
|
||||
|
||||
extern int ogs_dict_s6a_entry(char *conffile);
|
||||
|
||||
int ogs_diam_s6a_init(void)
|
||||
@@ -176,5 +180,9 @@ int ogs_diam_s6a_init(void)
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "MSISDN", &ogs_diam_s6a_msisdn);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "A-MSISDN", &ogs_diam_s6a_a_msisdn);
|
||||
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Supported-Features", &ogs_diam_s6a_supported_features);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List-ID", &ogs_diam_s6a_feature_list_id);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List", &ogs_diam_s6a_feature_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -159,6 +159,10 @@ extern struct dict_object *ogs_diam_s6a_software_version;
|
||||
extern struct dict_object *ogs_diam_s6a_msisdn;
|
||||
extern struct dict_object *ogs_diam_s6a_a_msisdn;
|
||||
|
||||
extern struct dict_object *ogs_diam_s6a_supported_features;
|
||||
extern struct dict_object *ogs_diam_s6a_feature_list_id;
|
||||
extern struct dict_object *ogs_diam_s6a_feature_list;
|
||||
|
||||
typedef struct ogs_diam_e_utran_vector_s {
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
uint8_t xres_len;
|
||||
|
@@ -958,6 +958,97 @@ typedef struct ogs_media_component_s {
|
||||
int num_of_sub;
|
||||
} ogs_media_component_t;
|
||||
|
||||
#define OGS_MAX_NUM_OF_SPT 20
|
||||
#define OGS_MAX_NUM_OF_IFC 20
|
||||
|
||||
/*
|
||||
* Defines matching mechanism type of SPT
|
||||
*/
|
||||
typedef enum {
|
||||
OGS_SPT_INVALID_TYPE,
|
||||
OGS_SPT_HAS_METHOD,
|
||||
OGS_SPT_HAS_SESSION_CASE,
|
||||
OGS_SPT_HAS_SIP_HEADER,
|
||||
OGS_SPT_HAS_SDP_LINE,
|
||||
OGS_SPT_HAS_REQUEST_URI,
|
||||
} ogs_spt_type_e;
|
||||
|
||||
/**************************************************
|
||||
* Service Point Trigger Structure (SPT) */
|
||||
typedef struct ogs_spt_s {
|
||||
/* Matching mechanism type of SPT */
|
||||
ogs_spt_type_e type;
|
||||
/* Indicates if the Service Point Trigger instance is negated */
|
||||
int condition_negated;
|
||||
/* The SPT group or list of SPT groups assigned to the SPT */
|
||||
int group;
|
||||
/* The method of the SIP request */
|
||||
const char *method;
|
||||
/* The direction of the SIP request as evaluated by the S-CSCF */
|
||||
int session_case;
|
||||
/* A header in the SIP request*/
|
||||
const char *header;
|
||||
/* Optionally the value of the header in the SIP request */
|
||||
const char *header_content;
|
||||
/* A SDP line within the body (if any) of a SIP request */
|
||||
const char *sdp_line;
|
||||
/* Optionally the value in the SDP line of a SIP request */
|
||||
const char *sdp_line_content;
|
||||
/* The request-URI of the SIP request */
|
||||
const char *request_uri;
|
||||
} ogs_spt_t;
|
||||
|
||||
/*
|
||||
* Defines what logical operators should be used between SPTs belonging to
|
||||
* different groups
|
||||
*/
|
||||
typedef enum {
|
||||
OGS_DISJUNCTIVE_NORMAL_FORMAT, /* an ORed set of ANDed subsets */
|
||||
OGS_CONJUNCTIVE_NORMAL_FORMAT /* an ANDed set of ORed subsets */
|
||||
} ogs_condition_type_cnf_e;
|
||||
|
||||
/**************************************************
|
||||
* Trigger Point Structure
|
||||
* Each TriggerPoint is made up of Service Point Trigger (SPTs) which are
|
||||
* individual rules that are matched or not matched, that are either combined
|
||||
* as logical AND or logical OR statements when evaluated.
|
||||
*/
|
||||
typedef struct ogs_trigger_point_s {
|
||||
int num_of_spt;
|
||||
ogs_condition_type_cnf_e condition_type_cnf;
|
||||
ogs_spt_t spt[OGS_MAX_NUM_OF_SPT];
|
||||
} ogs_trigger_point_t;
|
||||
|
||||
/**************************************************
|
||||
* Application Server Structure */
|
||||
typedef struct ogs_application_server_s {
|
||||
const char *server_name;
|
||||
int default_handling;
|
||||
} ogs_application_server_t;
|
||||
|
||||
/**************************************************
|
||||
* IFC Structure
|
||||
* 3GPP TS 29.562
|
||||
*/
|
||||
typedef struct ogs_ifc_s {
|
||||
/*
|
||||
* The priority of the IFC.
|
||||
* The higher the Priority Number the lower the priority of the Filter
|
||||
* Criteria is
|
||||
*/
|
||||
int priority;
|
||||
/*
|
||||
* The conditions that should be checked to find out
|
||||
* if the indicated Application Server should be contacted or not
|
||||
*/
|
||||
ogs_trigger_point_t trigger_point;
|
||||
/*
|
||||
* the Application Server which shall be triggered
|
||||
* if the conditions are met
|
||||
*/
|
||||
ogs_application_server_t application_server;
|
||||
} ogs_ifc_t;
|
||||
|
||||
typedef struct ogs_ims_data_s {
|
||||
int num_of_msisdn;
|
||||
struct {
|
||||
@@ -969,6 +1060,9 @@ typedef struct ogs_ims_data_s {
|
||||
#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;
|
||||
|
||||
int num_of_ifc;
|
||||
ogs_ifc_t ifc[OGS_MAX_NUM_OF_IFC];
|
||||
} ogs_ims_data_t;
|
||||
|
||||
void ogs_ims_data_free(ogs_ims_data_t *ims_data);
|
||||
|
@@ -738,6 +738,26 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message)
|
||||
ogs_free(fields);
|
||||
}
|
||||
|
||||
}
|
||||
if (message->param.num_of_fields) {
|
||||
char *fields;
|
||||
|
||||
fields = ogs_strdup(message->param.fields[0]);
|
||||
if (!fields) {
|
||||
ogs_error("ogs_strdup() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 1; i < message->param.num_of_fields; i++)
|
||||
fields = ogs_mstrcatf(
|
||||
fields, ",%s", message->param.fields[i]);
|
||||
|
||||
if (fields) {
|
||||
ogs_sbi_header_set(request->http.params,
|
||||
OGS_SBI_PARAM_FIELDS, fields);
|
||||
ogs_free(fields);
|
||||
}
|
||||
|
||||
}
|
||||
if (message->param.ipv4addr) {
|
||||
ogs_sbi_header_set(request->http.params,
|
||||
|
@@ -364,6 +364,11 @@ extern "C" {
|
||||
#define OGS_SBI_PARAM_FIELDS_NSSAI "nssai"
|
||||
#define OGS_SBI_MAX_NUM_OF_FIELDS 8
|
||||
|
||||
#define OGS_SBI_PARAM_FIELDS_GPSIS "gpsis"
|
||||
#define OGS_SBI_PARAM_FIELDS_SUBSCRIBED_UE_AMBR "subscribedUeAmbr"
|
||||
#define OGS_SBI_PARAM_FIELDS_NSSAI "nssai"
|
||||
#define OGS_SBI_MAX_NUM_OF_FIELDS 8
|
||||
|
||||
#define OGS_SBI_CONTENT_JSON_TYPE \
|
||||
OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE
|
||||
#define OGS_SBI_CONTENT_PROBLEM_TYPE \
|
||||
|
@@ -923,7 +923,7 @@ char *hss_cx_download_user_data(
|
||||
hss_impu_t *impu = NULL;
|
||||
|
||||
bool barring_indication_presence = true;
|
||||
int i;
|
||||
int i, n, m;
|
||||
|
||||
ogs_assert(user_name);
|
||||
ogs_assert(visited_network_identifier);
|
||||
@@ -1011,7 +1011,160 @@ char *hss_cx_download_user_data(
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
if(self.sms_over_ims) {
|
||||
/* IFC data */
|
||||
for (n = 0; n < ims_data->num_of_ifc; n++) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_ifc_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* priority */
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_priority_s,
|
||||
ims_data->ifc[n].priority,
|
||||
ogs_diam_cx_xml_priority_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* trigger point */
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_tp_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_cnf_s,
|
||||
ims_data->ifc[n].trigger_point.condition_type_cnf,
|
||||
ogs_diam_cx_xml_cnf_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* SPTs */
|
||||
for (m = 0; m < ims_data->ifc[n].trigger_point.num_of_spt;
|
||||
m++) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_spt_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* condition negated */
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_condition_negated_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].
|
||||
condition_negated,
|
||||
ogs_diam_cx_xml_condition_negated_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* group */
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_group_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].group,
|
||||
ogs_diam_cx_xml_group_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* method */
|
||||
if (ims_data->ifc[n].trigger_point.spt[m].type ==
|
||||
OGS_SPT_HAS_METHOD) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_method_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].
|
||||
method,
|
||||
ogs_diam_cx_xml_method_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
/* session case */
|
||||
if (ims_data->ifc[n].trigger_point.spt[m].type ==
|
||||
OGS_SPT_HAS_SESSION_CASE) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_session_case_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].
|
||||
session_case,
|
||||
ogs_diam_cx_xml_session_case_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
/* sip header */
|
||||
if (ims_data->ifc[n].trigger_point.spt[m].type ==
|
||||
OGS_SPT_HAS_SIP_HEADER) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_sip_hdr_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_header_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].
|
||||
header,
|
||||
ogs_diam_cx_xml_header_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
if (ims_data->ifc[n].trigger_point.spt[m].
|
||||
header_content) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_content_s,
|
||||
ims_data->ifc[n].trigger_point.
|
||||
spt[m].header_content,
|
||||
ogs_diam_cx_xml_content_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_sip_hdr_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
/* request uri */
|
||||
if (ims_data->ifc[n].trigger_point.spt[m].type ==
|
||||
OGS_SPT_HAS_REQUEST_URI) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_req_uri_s,
|
||||
ims_data->ifc[n].trigger_point.spt[m].
|
||||
request_uri,
|
||||
ogs_diam_cx_xml_req_uri_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
/* extension */
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_extension_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_spt_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_tp_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
/* application server */
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_app_server_s);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%s%s",
|
||||
ogs_diam_cx_xml_server_name_s,
|
||||
ims_data->ifc[n].application_server.server_name,
|
||||
ogs_diam_cx_xml_server_name_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s%d%s",
|
||||
ogs_diam_cx_xml_default_handling_s,
|
||||
ims_data->ifc[n].application_server.
|
||||
default_handling,
|
||||
ogs_diam_cx_xml_default_handling_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_app_server_e);
|
||||
ogs_assert(user_data);
|
||||
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_ifc_e);
|
||||
ogs_assert(user_data);
|
||||
}
|
||||
|
||||
if (self.sms_over_ims) {
|
||||
user_data = ogs_mstrcatf(user_data, "%s",
|
||||
ogs_diam_cx_xml_ifc_s);
|
||||
ogs_assert(user_data);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -974,6 +974,76 @@ static int hss_ogs_diam_s6a_ulr_cb( struct msg **msg, struct avp *avp,
|
||||
ans, OGS_DIAM_S6A_APPLICATION_ID);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/*
|
||||
* AVP 628 Supported-Features
|
||||
* AVP 629 Feature-List-ID: 1
|
||||
* AVP 630 Feature-List: (misc subscriber restrictions)
|
||||
*/
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_supported_features, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_vendor_id, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_3GPP_VENDOR_ID;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_feature_list_id, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 1;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_feature_list, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = 0x0000000b;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/*
|
||||
* AVP 628 Supported-Features
|
||||
* AVP 629 Feature-List-ID: 2
|
||||
* AVP 630 Feature-List: (“NR as Secondary RAT: Supported”)
|
||||
*/
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_supported_features, 0, &avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_vendor_id, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = OGS_3GPP_VENDOR_ID;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_feature_list_id, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.i32 = 2;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_new(ogs_diam_s6a_feature_list, 0, &avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
val.u32 = 0x08000001;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
ogs_assert(ret == 0);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
|
||||
ogs_assert(ret == 0);
|
||||
|
||||
/* Send the answer */
|
||||
ret = fd_msg_send(msg, NULL, NULL);
|
||||
ogs_assert(ret == 0);
|
||||
|
@@ -34,6 +34,7 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
||||
OpenAPI_subscribed_default_qos_t SubsDefQos;
|
||||
OpenAPI_arp_t Arp;
|
||||
OpenAPI_snssai_t sNssai;
|
||||
OpenAPI_user_location_t ueLocation;
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(sess->sm_context_ref);
|
||||
@@ -50,6 +51,7 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
||||
memset(&SmPolicyContextData, 0, sizeof(SmPolicyContextData));
|
||||
memset(&sNssai, 0, sizeof(sNssai));
|
||||
memset(&SubsSessAmbr, 0, sizeof(SubsSessAmbr));
|
||||
memset(&ueLocation, 0, sizeof(ueLocation));
|
||||
|
||||
SmPolicyContextData.supi = smf_ue->supi;
|
||||
if (!SmPolicyContextData.supi) {
|
||||
@@ -67,6 +69,12 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Currently hard-coded to "00000800";
|
||||
* replace with dynamic value if needed in future
|
||||
*/
|
||||
SmPolicyContextData.chargingcharacteristics = (char *)"00000800";
|
||||
|
||||
/*
|
||||
* Use ogs_sbi_supi_in_vplmn() instead of ogs_sbi_plmn_id_in_vplmn().
|
||||
* This is because some vendors might not use the full DNN in LBO and
|
||||
@@ -139,6 +147,8 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
||||
goto end;
|
||||
}
|
||||
|
||||
SmPolicyContextData.rat_type = OpenAPI_rat_type_NR;
|
||||
|
||||
SmPolicyContextData.serving_network =
|
||||
ogs_sbi_build_plmn_id_nid(&sess->serving_plmn_id);
|
||||
if (!SmPolicyContextData.serving_network) {
|
||||
@@ -146,6 +156,28 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
||||
goto end;
|
||||
}
|
||||
|
||||
ueLocation.nr_location = ogs_sbi_build_nr_location(
|
||||
&sess->nr_tai, &sess->nr_cgi);
|
||||
if (!ueLocation.nr_location) {
|
||||
ogs_error("ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
|
||||
SmPolicyContextData.user_location_info = &ueLocation;
|
||||
|
||||
SmPolicyContextData.ue_time_zone =
|
||||
ogs_sbi_timezone_string(ogs_timezone());
|
||||
if (!SmPolicyContextData.ue_time_zone) {
|
||||
ogs_error("SmPolicyContextData.ue_time_zone");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sess->ipv4) {
|
||||
SmPolicyContextData.ipv4_address =
|
||||
ogs_ipv4_to_string(sess->ipv4->addr[0]);
|
||||
@@ -263,6 +295,14 @@ end:
|
||||
if (SmPolicyContextData.serving_network)
|
||||
ogs_sbi_free_plmn_id_nid(SmPolicyContextData.serving_network);
|
||||
|
||||
if (ueLocation.nr_location) {
|
||||
if (ueLocation.nr_location->ue_location_timestamp)
|
||||
ogs_free(ueLocation.nr_location->ue_location_timestamp);
|
||||
ogs_sbi_free_nr_location(ueLocation.nr_location);
|
||||
}
|
||||
if (SmPolicyContextData.ue_time_zone)
|
||||
ogs_free(SmPolicyContextData.ue_time_zone);
|
||||
|
||||
if (sNssai.sd)
|
||||
ogs_free(sNssai.sd);
|
||||
|
||||
|
Reference in New Issue
Block a user