diff --git a/lib/core/ogs-3gpp-types.c b/lib/core/ogs-3gpp-types.c index 2c7b3916a..3f6d72248 100644 --- a/lib/core/ogs-3gpp-types.c +++ b/lib/core/ogs-3gpp-types.c @@ -558,6 +558,8 @@ void ogs_subscription_data_free(ogs_subscription_data_t *subscription_data) } subscription_data->num_of_slice = 0; + + subscription_data->num_of_msisdn = 0; } void ogs_session_data_free(ogs_session_data_t *session_data) diff --git a/lib/core/ogs-conv.c b/lib/core/ogs-conv.c index bb4d312bf..5ddbb0f8e 100644 --- a/lib/core/ogs-conv.c +++ b/lib/core/ogs-conv.c @@ -234,11 +234,12 @@ uint64_t ogs_uint64_from_string(char *str) void ogs_extract_digit_from_string(char *digit, char *string) { bool extracting = false; + int i = 0; ogs_assert(string); ogs_assert(digit); - while (*string) { + while (*string && i < OGS_MAX_IMSI_BCD_LEN) { if (*string >= '0' && *string <= '9') { *digit++ = *string; extracting = true; @@ -246,6 +247,7 @@ void ogs_extract_digit_from_string(char *digit, char *string) break; } string++; + i++; } *digit = 0; diff --git a/lib/dbi/ims.c b/lib/dbi/ims.c new file mode 100644 index 000000000..bdff0425c --- /dev/null +++ b/lib/dbi/ims.c @@ -0,0 +1,214 @@ +/* + * 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 . + */ + +#include "ogs-dbi.h" + +int ogs_dbi_msisdn_data( + char *imsi_or_msisdn_bcd, ogs_msisdn_data_t *msisdn_data) +{ + int rv = OGS_OK; + mongoc_cursor_t *cursor = NULL; + bson_t *query = NULL; + bson_error_t error; + const bson_t *document; + bson_iter_t iter; + bson_iter_t child1_iter; + const char *utf8 = NULL; + uint32_t length = 0; + + ogs_msisdn_data_t zero_data; + + ogs_assert(msisdn_data); + ogs_assert(imsi_or_msisdn_bcd); + + memset(&zero_data, 0, sizeof(zero_data)); + + /* msisdn_data should be initialized to zero */ + ogs_assert(memcmp(msisdn_data, &zero_data, sizeof(zero_data)) == 0); + + query = BCON_NEW("$or", + "[", + "{", "imsi", BCON_UTF8(imsi_or_msisdn_bcd), "}", + "{", "msisdn", BCON_UTF8(imsi_or_msisdn_bcd), "}", + "]"); +#if MONGOC_MAJOR_VERSION >= 1 && MONGOC_MINOR_VERSION >= 5 + cursor = mongoc_collection_find_with_opts( + ogs_mongoc()->collection.subscriber, query, NULL, NULL); +#else + cursor = mongoc_collection_find(ogs_mongoc()->collection.subscriber, + MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); +#endif + + if (!mongoc_cursor_next(cursor, &document)) { + ogs_error("[%s] Cannot find IMSI or MSISDN in DB", imsi_or_msisdn_bcd); + + rv = OGS_ERROR; + goto out; + } + + if (mongoc_cursor_error(cursor, &error)) { + ogs_error("Cursor Failure: %s", error.message); + + rv = OGS_ERROR; + goto out; + } + + if (!bson_iter_init(&iter, document)) { + ogs_error("bson_iter_init failed in this document"); + + rv = OGS_ERROR; + goto out; + } + + while (bson_iter_next(&iter)) { + const char *key = bson_iter_key(&iter); + if (!strcmp(key, "imsi") && + BSON_ITER_HOLDS_UTF8(&iter)) { + utf8 = bson_iter_utf8(&iter, &length); + ogs_cpystrn(msisdn_data->imsi.bcd, + utf8, ogs_min(length, OGS_MAX_IMSI_BCD_LEN)+1); + ogs_bcd_to_buffer( + msisdn_data->imsi.bcd, + msisdn_data->imsi.buf, &msisdn_data->imsi.len); + } else if (!strcmp(key, "msisdn") && + BSON_ITER_HOLDS_ARRAY(&iter)) { + int msisdn_index = 0; + + bson_iter_recurse(&iter, &child1_iter); + while (bson_iter_next(&child1_iter)) { + ogs_assert(msisdn_index < OGS_MAX_NUM_OF_MSISDN); + + if (BSON_ITER_HOLDS_UTF8(&child1_iter)) { + utf8 = bson_iter_utf8(&child1_iter, &length); + ogs_cpystrn(msisdn_data->msisdn[msisdn_index].bcd, + utf8, ogs_min(length, OGS_MAX_MSISDN_BCD_LEN)+1); + ogs_bcd_to_buffer( + msisdn_data->msisdn[msisdn_index].bcd, + msisdn_data->msisdn[msisdn_index].buf, + &msisdn_data->msisdn[msisdn_index].len); + + msisdn_index++; + } + } + msisdn_data->num_of_msisdn = msisdn_index; + } + } + +out: + if (query) bson_destroy(query); + if (cursor) mongoc_cursor_destroy(cursor); + + return rv; +} + +int ogs_dbi_ims_data(char *supi, ogs_ims_data_t *ims_data) +{ + int rv = OGS_OK; + mongoc_cursor_t *cursor = NULL; + bson_t *query = NULL; + bson_error_t error; + const bson_t *document; + bson_iter_t iter; + bson_iter_t child1_iter; + const char *utf8 = NULL; + uint32_t length = 0; + + char *supi_type = NULL; + char *supi_id = NULL; + + ogs_ims_data_t zero_data; + + ogs_assert(ims_data); + ogs_assert(supi); + + memset(&zero_data, 0, sizeof(zero_data)); + + /* ims_data should be initialized to zero */ + ogs_assert(memcmp(ims_data, &zero_data, sizeof(zero_data)) == 0); + + supi_type = ogs_id_get_type(supi); + ogs_assert(supi_type); + supi_id = ogs_id_get_value(supi); + ogs_assert(supi_id); + + query = BCON_NEW(supi_type, BCON_UTF8(supi_id)); +#if MONGOC_MAJOR_VERSION >= 1 && MONGOC_MINOR_VERSION >= 5 + cursor = mongoc_collection_find_with_opts( + ogs_mongoc()->collection.subscriber, query, NULL, NULL); +#else + cursor = mongoc_collection_find(ogs_mongoc()->collection.subscriber, + MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); +#endif + + if (!mongoc_cursor_next(cursor, &document)) { + ogs_error("[%s] Cannot find IMSI in DB", supi); + + rv = OGS_ERROR; + goto out; + } + + if (mongoc_cursor_error(cursor, &error)) { + ogs_error("Cursor Failure: %s", error.message); + + rv = OGS_ERROR; + goto out; + } + + if (!bson_iter_init(&iter, document)) { + ogs_error("bson_iter_init failed in this document"); + + rv = OGS_ERROR; + goto out; + } + + while (bson_iter_next(&iter)) { + const char *key = bson_iter_key(&iter); + if (!strcmp(key, "msisdn") && + BSON_ITER_HOLDS_ARRAY(&iter)) { + int msisdn_index = 0; + + bson_iter_recurse(&iter, &child1_iter); + while (bson_iter_next(&child1_iter)) { + ogs_assert(msisdn_index < OGS_MAX_NUM_OF_MSISDN); + + if (BSON_ITER_HOLDS_UTF8(&child1_iter)) { + utf8 = bson_iter_utf8(&child1_iter, &length); + ogs_cpystrn(ims_data->msisdn[msisdn_index].bcd, + utf8, ogs_min(length, OGS_MAX_MSISDN_BCD_LEN)+1); + ogs_bcd_to_buffer( + ims_data->msisdn[msisdn_index].bcd, + ims_data->msisdn[msisdn_index].buf, + &ims_data->msisdn[msisdn_index].len); + + msisdn_index++; + } + } + ims_data->num_of_msisdn = msisdn_index; + } + } + +out: + if (query) bson_destroy(query); + if (cursor) mongoc_cursor_destroy(cursor); + + ogs_free(supi_type); + ogs_free(supi_id); + + return rv; +} diff --git a/lib/dbi/ims.h b/lib/dbi/ims.h new file mode 100644 index 000000000..82fcfe3b8 --- /dev/null +++ b/lib/dbi/ims.h @@ -0,0 +1,64 @@ +/* + * 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_DBI_INSIDE) && !defined(OGS_DBI_COMPILATION) +#error "This header cannot be included directly." +#endif + +#ifndef OGS_DBI_IMS_H +#define OGS_DBI_IMS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ogs_msisdn_data_s { + struct { + uint8_t buf[OGS_MAX_IMSI_LEN]; + int len; + char bcd[OGS_MAX_IMSI_BCD_LEN+1]; + } imsi; + + 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]; +} ogs_msisdn_data_t; + +int ogs_dbi_msisdn_data( + char *imsi_or_msisdn_bcd, ogs_msisdn_data_t *msisdn_data); + +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]; +} ogs_ims_data_t; + +int ogs_dbi_ims_data(char *supi, ogs_ims_data_t *ims_data); + +#ifdef __cplusplus +} +#endif + +#endif /* OGS_DBI_IMS_H */ diff --git a/lib/dbi/meson.build b/lib/dbi/meson.build index c430d59df..a48f47785 100644 --- a/lib/dbi/meson.build +++ b/lib/dbi/meson.build @@ -23,6 +23,7 @@ libdbi_sources = files(''' ogs-mongoc.c subscription.c session.c + ims.c '''.split()) libmongoc_dep = dependency('libmongoc-1.0') diff --git a/lib/dbi/ogs-dbi.h b/lib/dbi/ogs-dbi.h index 42a681554..f5e7818a3 100644 --- a/lib/dbi/ogs-dbi.h +++ b/lib/dbi/ogs-dbi.h @@ -28,6 +28,7 @@ #include "dbi/ogs-mongoc.h" #include "dbi/subscription.h" #include "dbi/session.h" +#include "dbi/ims.h" #undef OGS_DBI_INSIDE diff --git a/lib/diameter/cx/message.c b/lib/diameter/cx/message.c index d6d1c0dbe..93d2fa8bb 100644 --- a/lib/diameter/cx/message.c +++ b/lib/diameter/cx/message.c @@ -33,6 +33,9 @@ struct dict_object *ogs_diam_cx_cmd_maa = NULL; struct dict_object *ogs_diam_cx_cmd_sar = NULL; struct dict_object *ogs_diam_cx_cmd_saa = NULL; +struct dict_object *ogs_diam_cx_cmd_lir = NULL; +struct dict_object *ogs_diam_cx_cmd_lia = NULL; + struct dict_object *ogs_diam_cx_public_identity = NULL; struct dict_object *ogs_diam_cx_visited_network_identifier = NULL; struct dict_object *ogs_diam_cx_server_name = NULL; @@ -160,6 +163,11 @@ int ogs_diam_cx_init(void) CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "3GPP/Server-Assignment-Answer", &ogs_diam_cx_cmd_saa); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, + "3GPP/Location-Info-Request", &ogs_diam_cx_cmd_lir); + CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, + "3GPP/Location-Info-Answer", &ogs_diam_cx_cmd_lia); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Public-Identity", &ogs_diam_cx_public_identity); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, diff --git a/lib/diameter/cx/message.h b/lib/diameter/cx/message.h index 012894533..3951507d0 100644 --- a/lib/diameter/cx/message.h +++ b/lib/diameter/cx/message.h @@ -38,6 +38,8 @@ extern struct dict_object *ogs_diam_cx_cmd_mar; extern struct dict_object *ogs_diam_cx_cmd_maa; extern struct dict_object *ogs_diam_cx_cmd_sar; extern struct dict_object *ogs_diam_cx_cmd_saa; +extern struct dict_object *ogs_diam_cx_cmd_lir; +extern struct dict_object *ogs_diam_cx_cmd_lia; extern struct dict_object *ogs_diam_cx_public_identity; extern struct dict_object *ogs_diam_cx_visited_network_identifier; diff --git a/src/hss/hss-context.c b/src/hss/hss-context.c index 525d6927c..0566cbe9c 100644 --- a/src/hss/hss-context.c +++ b/src/hss/hss-context.c @@ -40,7 +40,8 @@ static char *impi_get_server_name(hss_impi_t *impi); static hss_impu_t *impu_add(hss_impi_t *impi, char *id); static void impu_remove(hss_impu_t *impu); static void impu_remove_all(hss_impi_t *impi); -static hss_impu_t *impu_find_by_id(hss_impi_t *impi, char *id); +static hss_impu_t *impu_find_by_id(char *id); +static hss_impu_t *impu_find_by_impi_and_id(hss_impi_t *impi, char *id); hss_context_t* hss_self(void) { @@ -66,6 +67,7 @@ void hss_context_init(void) ogs_pool_init(&impu_pool, ogs_app()->pool.impu); self.impi_hash = ogs_hash_make(); + self.impu_hash = ogs_hash_make(); ogs_thread_mutex_init(&self.db_lock); ogs_thread_mutex_init(&self.cx_lock); @@ -81,6 +83,8 @@ void hss_context_final(void) ogs_assert(self.impi_hash); ogs_hash_destroy(self.impi_hash); + ogs_assert(self.impu_hash); + ogs_hash_destroy(self.impu_hash); ogs_pool_final(&impi_pool); ogs_pool_final(&impu_pool); @@ -365,6 +369,42 @@ int hss_db_subscription_data( return rv; } +int hss_db_msisdn_data(char *imsi_or_msisdn_bcd, ogs_msisdn_data_t *msisdn_data) +{ + int rv; + + ogs_assert(imsi_or_msisdn_bcd); + ogs_assert(msisdn_data); + + ogs_thread_mutex_lock(&self.db_lock); + + rv = ogs_dbi_msisdn_data(imsi_or_msisdn_bcd, msisdn_data); + + ogs_thread_mutex_unlock(&self.db_lock); + + return rv; +} + +int hss_db_ims_data(char *imsi_bcd, ogs_ims_data_t *ims_data) +{ + int rv; + char *supi = NULL; + + ogs_assert(imsi_bcd); + ogs_assert(ims_data); + + ogs_thread_mutex_lock(&self.db_lock); + supi = ogs_msprintf("%s-%s", OGS_ID_SUPI_TYPE_IMSI, imsi_bcd); + ogs_assert(supi); + + rv = ogs_dbi_ims_data(supi, ims_data); + + ogs_free(supi); + ogs_thread_mutex_unlock(&self.db_lock); + + return rv; +} + static hss_impi_t *impi_add(char *id) { hss_impi_t *impi = NULL; @@ -397,6 +437,9 @@ static void impi_remove(hss_impi_t *impi) ogs_hash_set(self.impi_hash, impi->id, strlen(impi->id), NULL); ogs_free(impi->id); + if (impi->imsi_bcd) + ogs_free(impi->imsi_bcd); + ogs_pool_free(&impi_pool, impi); } @@ -442,6 +485,8 @@ static hss_impu_t *impu_add(hss_impi_t *impi, char *id) impu->id = ogs_strdup(id); ogs_assert(impu->id); + ogs_hash_set(self.impu_hash, impu->id, strlen(impu->id), impu); + impu->impi = impi; ogs_list_add(&impi->impu_list, impu); @@ -459,6 +504,7 @@ static void impu_remove(hss_impu_t *impu) ogs_list_remove(&impi->impu_list, impu); ogs_assert(impu->id); + ogs_hash_set(self.impu_hash, impu->id, strlen(impu->id), NULL); ogs_free(impu->id); if (impu->server_name) @@ -475,7 +521,13 @@ static void impu_remove_all(hss_impi_t *impi) impu_remove(impu); } -static hss_impu_t *impu_find_by_id(hss_impi_t *impi, char *id) +static hss_impu_t *impu_find_by_id(char *id) +{ + ogs_assert(id); + return (hss_impu_t *)ogs_hash_get(self.impu_hash, id, strlen(id)); +} + +static hss_impu_t *impu_find_by_impi_and_id(hss_impi_t *impi, char *id) { hss_impu_t *impu = NULL; @@ -506,7 +558,7 @@ void hss_cx_associate_identity(char *user_name, char *public_identity) ogs_assert(impi); } - impu = impu_find_by_id(impi, public_identity); + impu = impu_find_by_id(public_identity); if (!impu) { impu = impu_add(impi, public_identity); ogs_assert(impu); @@ -526,7 +578,7 @@ bool hss_cx_identity_is_associated(char *user_name, char *public_identity) impi = impi_find_by_id(user_name); if (impi) { - impu = impu_find_by_id(impi, public_identity); + impu = impu_find_by_impi_and_id(impi, public_identity); if (impu) { match_result = true; } @@ -537,7 +589,50 @@ bool hss_cx_identity_is_associated(char *user_name, char *public_identity) return match_result; } -char *hss_cx_get_server_name(char *user_name, char *public_identity) +char *hss_cx_get_imsi_bcd(char *public_identity) +{ + hss_impi_t *impi = NULL; + hss_impu_t *impu = NULL; + + char *imsi_bcd = NULL; + + ogs_thread_mutex_lock(&self.cx_lock); + + impu = impu_find_by_id(public_identity); + if (impu) { + impi = impu->impi; + ogs_assert(impi); + + imsi_bcd = impi->imsi_bcd; + } + + ogs_thread_mutex_unlock(&self.cx_lock); + + return imsi_bcd;; +} + +void hss_cx_set_imsi_bcd(char *user_name, char *imsi_bcd) +{ + hss_impi_t *impi = NULL; + + ogs_assert(user_name); + ogs_assert(imsi_bcd); + + ogs_thread_mutex_lock(&self.cx_lock); + + impi = impi_find_by_id(user_name); + ogs_assert(impi); + + if (impi->imsi_bcd) + ogs_free(impi->imsi_bcd); + + impi->imsi_bcd = ogs_strdup(imsi_bcd); + ogs_assert(impi->imsi_bcd); + + ogs_thread_mutex_unlock(&self.cx_lock); +} + +char *hss_cx_get_server_name(char *public_identity) { char *server_name = NULL; @@ -546,15 +641,15 @@ char *hss_cx_get_server_name(char *user_name, char *public_identity) ogs_thread_mutex_lock(&self.cx_lock); - impi = impi_find_by_id(user_name); - ogs_assert(impi); + impu = impu_find_by_id(public_identity); + if (impu) { + server_name = impu->server_name; + if (!server_name) { + impi = impu->impi; + ogs_assert(impi); - impu = impu_find_by_id(impi, public_identity); - ogs_assert(impu); - - server_name = impu->server_name; - if (!server_name) { - server_name = impi_get_server_name(impi); + server_name = impi_get_server_name(impi); + } } ogs_thread_mutex_unlock(&self.cx_lock); @@ -563,18 +658,13 @@ char *hss_cx_get_server_name(char *user_name, char *public_identity) } void hss_cx_set_server_name( - char *user_name, char *public_identity, - char *server_name, bool overwrite) + char *public_identity, char *server_name, bool overwrite) { - hss_impi_t *impi = NULL; hss_impu_t *impu = NULL; ogs_thread_mutex_lock(&self.cx_lock); - impi = impi_find_by_id(user_name); - ogs_assert(impi); - - impu = impu_find_by_id(impi, public_identity); + impu = impu_find_by_id(public_identity); ogs_assert(impu); if (!impu->server_name) { @@ -597,3 +687,110 @@ void hss_cx_set_server_name( ogs_thread_mutex_unlock(&self.cx_lock); } + +char *hss_cx_download_user_data(char *user_name, ogs_ims_data_t *ims_data) +{ + char *user_data = NULL; + + hss_impi_t *impi = NULL; + hss_impu_t *impu = NULL; + + bool barring_indication_presence = true; + int i; + + ogs_assert(user_name); + ogs_assert(ims_data); + + /* Download User-Data */ + for (i = 0; i < ims_data->num_of_msisdn; i++) { + char *public_identity = NULL; + + public_identity = ogs_msprintf("sip:%s", ims_data->msisdn[i].bcd); + ogs_assert(public_identity); + hss_cx_associate_identity(user_name, public_identity); + ogs_free(public_identity); + + public_identity = ogs_msprintf("tel:%s", ims_data->msisdn[i].bcd); + ogs_assert(public_identity); + hss_cx_associate_identity(user_name, public_identity); + ogs_free(public_identity); + } + + + /* Generate XML Data */ + + ogs_thread_mutex_lock(&self.cx_lock); + + user_data = ogs_strdup(ogs_diam_cx_xml_version); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, "%s", + ogs_diam_cx_xml_ims_subscription_s); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, "%s%s%s", + ogs_diam_cx_xml_private_id_s, + user_name, + ogs_diam_cx_xml_private_id_e); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, "%s", + ogs_diam_cx_xml_service_profile_s); + ogs_assert(user_data); + + impi = impi_find_by_id(user_name); + ogs_assert(impi); + + barring_indication_presence = true; + + ogs_list_for_each(&impi->impu_list, impu) { + user_data = ogs_mstrcatf(user_data, "%s", + ogs_diam_cx_xml_public_id_s); + ogs_assert(user_data); + + if (barring_indication_presence == true) { + user_data = ogs_mstrcatf(user_data, "%s%s%s", + ogs_diam_cx_xml_barring_indication_s, + "1", + ogs_diam_cx_xml_barring_indication_e); + ogs_assert(user_data); + barring_indication_presence = false; + } + + user_data = ogs_mstrcatf(user_data, "%s%s%s", + ogs_diam_cx_xml_identity_s, + impu->id, + ogs_diam_cx_xml_identity_e); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, "%s", + ogs_diam_cx_xml_extension_s); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, "%s%s%s", + ogs_diam_cx_xml_identity_type_s, + "0", + ogs_diam_cx_xml_identity_type_e); + 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_public_id_e); + ogs_assert(user_data); + } + + user_data = ogs_mstrcatf(user_data, "%s", + ogs_diam_cx_xml_service_profile_e); + ogs_assert(user_data); + + user_data = ogs_mstrcatf(user_data, + "%s", ogs_diam_cx_xml_ims_subscription_e); + ogs_assert(user_data); + + ogs_thread_mutex_unlock(&self.cx_lock); + + return user_data; +} diff --git a/src/hss/hss-context.h b/src/hss/hss-context.h index 912107209..41423885f 100644 --- a/src/hss/hss-context.h +++ b/src/hss/hss-context.h @@ -43,12 +43,14 @@ typedef struct _hss_context_t { ogs_list_t impi_list; ogs_hash_t *impi_hash; /* hash table (IMPI) */ + ogs_hash_t *impu_hash; /* hash table (IMPU) */ } hss_context_t; typedef struct hss_impi_s { ogs_lnode_t lnode; char *id; + char *imsi_bcd; ogs_list_t impu_list; } hss_impi_t; @@ -75,13 +77,23 @@ int hss_db_increment_sqn(char *imsi_bcd); int hss_db_subscription_data( char *imsi_bcd, ogs_subscription_data_t *subscription_data); +int hss_db_msisdn_data( + char *imsi_or_msisdn_bcd, ogs_msisdn_data_t *msisdn_data); + +int hss_db_ims_data(char *imsi_bcd, ogs_ims_data_t *ims_data); + void hss_cx_associate_identity(char *user_name, char *public_identity); bool hss_cx_identity_is_associated(char *user_name, char *public_identity); -char *hss_cx_get_server_name(char *user_name, char *public_identity); +char *hss_cx_get_imsi_bcd(char *public_identity); +void hss_cx_set_imsi_bcd(char *user_name, char *imsi_bcd); + +char *hss_cx_get_server_name(char *public_identity); void hss_cx_set_server_name( - char *user_name, char *public_identity, - char *server_name, bool overwrite); + char *public_identity, char *server_name, bool overwrite); + +char *hss_cx_download_user_data(char *user_name, ogs_ims_data_t *ims_data); + #ifdef __cplusplus } diff --git a/src/hss/hss-cx-path.c b/src/hss/hss-cx-path.c index 99b8b080e..6898f08a4 100644 --- a/src/hss/hss-cx-path.c +++ b/src/hss/hss-cx-path.c @@ -30,9 +30,8 @@ static struct disp_hdl *hdl_cx_uar = NULL; static struct disp_hdl *hdl_cx_mar = NULL; /* handler for Server-Assignment-Request cb */ static struct disp_hdl *hdl_cx_sar = NULL; - -static char *download_user_data( - char *user_name, ogs_subscription_data_t *subscription_data); +/* handler for Location-Info-Request cb */ +static struct disp_hdl *hdl_cx_lir = NULL; /* Default callback for the application. */ static int hss_ogs_diam_cx_fb_cb(struct msg **msg, struct avp *avp, @@ -60,10 +59,9 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, char *public_identity = NULL; char *server_name = NULL; - char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; - char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; + char imsi_or_msisdn_bcd[OGS_MAX_IMSI_BCD_LEN+1]; - ogs_subscription_data_t subscription_data; + ogs_msisdn_data_t msisdn_data; ogs_assert(msg); @@ -75,7 +73,7 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ans = *msg; - /* Get User-Name AVP (Mandatory has already been checked) */ + /* Get User-Name AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -85,9 +83,9 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(user_name); - ogs_extract_digit_from_string(imsi_bcd, user_name); + ogs_extract_digit_from_string(imsi_or_msisdn_bcd, user_name); - /* Get Public-Identity AVP (Mandatory has already been checked) */ + /* Get Public-Identity AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -97,12 +95,11 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(public_identity); - ogs_extract_digit_from_string(msisdn_bcd, public_identity); - - memset(&subscription_data, 0, sizeof(ogs_subscription_data_t)); - rv = hss_db_subscription_data(imsi_bcd, &subscription_data); + memset(&msisdn_data, 0, sizeof(ogs_msisdn_data_t)); + rv = hss_db_msisdn_data(imsi_or_msisdn_bcd, &msisdn_data); if (rv != OGS_OK) { - ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd); + ogs_error("Cannot get MSISDN-Data for IMSI or MSISDN:'%s'", + imsi_or_msisdn_bcd); result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN; goto out; } @@ -112,19 +109,21 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, ans, OGS_DIAM_CX_APPLICATION_ID); ogs_assert(ret == 0); - /* Associate IMPI(User-Name) + IMPU(Public-Identity) */ + /* Associate IMPI(User-Name) with IMPU(Public-Identity) */ hss_cx_associate_identity(user_name, public_identity); - /* Get Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */ - server_name = hss_cx_get_server_name(user_name, public_identity); + /* Set IMSI for IMPI(User-Name) */ + hss_cx_set_imsi_bcd(user_name, msisdn_data.imsi.bcd); + + /* Get Server-Name by IMPU(Public-Identity) */ + server_name = hss_cx_get_server_name(public_identity); if (!server_name) result_code = OGS_DIAM_CX_FIRST_REGISTRATION; else result_code = OGS_DIAM_CX_SUBSEQUENT_REGISTRATION; /* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */ - ret = ogs_diam_message_experimental_rescode_set( - ans, result_code); + ret = ogs_diam_message_experimental_rescode_set(ans, result_code); ogs_assert(ret == 0); /* Set the Auth-Session-State AVP */ @@ -159,8 +158,6 @@ static int hss_ogs_diam_cx_uar_cb( struct msg **msg, struct avp *avp, ogs_diam_logger_self()->stats.nb_echoed++; ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - ogs_subscription_data_free(&subscription_data); - ogs_free(user_name); ogs_free(public_identity); @@ -188,8 +185,6 @@ out: ret = fd_msg_send(msg, NULL, NULL); ogs_assert(ret == 0); - ogs_subscription_data_free(&subscription_data); - ogs_free(user_name); ogs_free(public_identity); @@ -218,8 +213,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, char *server_name = NULL; char *authentication_scheme = NULL; - char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; - char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; + char *imsi_bcd = NULL; ogs_dbi_auth_info_t auth_info; uint8_t zero[OGS_RAND_LEN]; @@ -248,7 +242,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ans = *msg; - /* Get User-Name AVP (Mandatory has already been checked) */ + /* Get User-Name AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -258,9 +252,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(user_name); - ogs_extract_digit_from_string(imsi_bcd, user_name); - - /* Get Public-Identity AVP (Mandatory has already been checked) */ + /* Get Public-Identity AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -270,9 +262,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(public_identity); - ogs_extract_digit_from_string(msisdn_bcd, public_identity); - - /* Get Server-Name AVP (Mandatory has already been checked) */ + /* Get Server-Name AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_server_name, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -291,7 +281,16 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, goto out; } - /* Get the SIP-Auth-Data-Item AVP (Mandatory has already been checked) */ + /* Check if IMSI */ + imsi_bcd = hss_cx_get_imsi_bcd(public_identity); + if (!imsi_bcd) { + ogs_error("Cannot find IMSI for User-Name[%s] Public-Identity[%s]", + user_name, public_identity); + result_code = OGS_DIAM_CX_ERROR_IDENTITY_NOT_REGISTERED; + goto out; + } + + /* Get the SIP-Auth-Data-Item AVP (Mandatory) */ ret = fd_msg_search_avp( qry, ogs_diam_cx_sip_auth_data_item, &sip_auth_data_item_avp); ogs_assert(ret == 0); @@ -323,15 +322,16 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, goto out; } + /* DB : HSS Auth-Info */ rv = hss_db_auth_info(imsi_bcd, &auth_info); if (rv != OGS_OK) { - ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd); + ogs_error("Cannot get IMS-Data for IMSI:'%s'", imsi_bcd); result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN; goto out; } - /* Overwrite Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */ - hss_cx_set_server_name(user_name, public_identity, server_name, true); + /* Overwrite Server-Name for IMPU(Public-Identity) */ + hss_cx_set_server_name(public_identity, server_name, true); memset(zero, 0, sizeof(zero)); if (memcmp(auth_info.rand, zero, OGS_RAND_LEN) == 0) { @@ -390,24 +390,6 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, goto out; } -#if 0 /* Test Vector for ipsec_reg.pcapng */ - /* - * Ki : 8baf473f2f8fd09487cccbd7097c6862 - * OP : 11111111111111111111111111111111 - * OPc : 8E27B6AF0E692E750F32667A3B14605D - * open5gs SQN : 44254 (dec) - * Fhoss SQN : 00000000ad25 (hex) - * RAND : a0944c75ff3c4f0853a2f910aa1f104f - * AMF : c6e2f46c8f4280007f3bb9b84b7c3ff6 - * - * New SQN : 000017242898 (hex) - */ - - auth_info.sqn = 0x17242898; -#define RAND "a0944c75ff3c4f0853a2f910aa1f104f" - OGS_HEX(RAND, strlen(RAND), auth_info.rand); -#endif - milenage_generate(opc, auth_info.amf, auth_info.k, ogs_uint64_to_buffer(auth_info.sqn, OGS_SQN_LEN, sqn), auth_info.rand, autn, ik, ck, ak, xres, &xres_len); @@ -451,7 +433,7 @@ static int hss_ogs_diam_cx_mar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); - /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ + /* Set the Origin-Host, Origin-Realm, and Result-Code AVPs */ ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); ogs_assert(ret == 0); @@ -620,10 +602,9 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, char *server_name = NULL; char *user_data = NULL; - char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1]; - char msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; + char *imsi_bcd = NULL; - ogs_subscription_data_t subscription_data; + ogs_ims_data_t ims_data; ogs_assert(msg); @@ -635,7 +616,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ans = *msg; - /* Get User-Name AVP (Mandatory has already been checked) */ + /* Get User-Name AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_user_name, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -645,9 +626,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(user_name); - ogs_extract_digit_from_string(imsi_bcd, user_name); - - /* Get Public-Identity AVP (Mandatory has already been checked) */ + /* Get Public-Identity AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -657,17 +636,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); ogs_assert(public_identity); - ogs_extract_digit_from_string(msisdn_bcd, public_identity); - - memset(&subscription_data, 0, sizeof(ogs_subscription_data_t)); - rv = hss_db_subscription_data(imsi_bcd, &subscription_data); - if (rv != OGS_OK) { - ogs_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd); - result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN; - goto out; - } - - /* Get Server-Name AVP (Mandatory has already been checked) */ + /* Get Server-Name AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_server_name, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -686,8 +655,26 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, goto out; } - /* Overwrite Server-Name for IMPI(User-Name) + IMPU(Public-Identity) */ - hss_cx_set_server_name(user_name, public_identity, server_name, true); + /* Check if IMSI */ + imsi_bcd = hss_cx_get_imsi_bcd(public_identity); + if (!imsi_bcd) { + ogs_error("Cannot find IMSI for User-Name[%s] Public-Identity[%s]", + user_name, public_identity); + result_code = OGS_DIAM_CX_ERROR_IDENTITY_NOT_REGISTERED; + goto out; + } + + /* DB : HSS IMS Service Profile */ + memset(&ims_data, 0, sizeof(ogs_ims_data_t)); + rv = hss_db_ims_data(imsi_bcd, &ims_data); + if (rv != OGS_OK) { + ogs_error("Cannot get IMS-Data for IMSI:'%s'", imsi_bcd); + result_code = OGS_DIAM_CX_ERROR_USER_UNKNOWN; + goto out; + } + + /* Overwrite Server-Name for IMPU(Public-Identity) */ + hss_cx_set_server_name(public_identity, server_name, true); /* Set Vendor-Specific-Application-Id AVP */ ret = ogs_diam_message_vendor_specific_appid_set( @@ -703,7 +690,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); - /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ + /* Set the Origin-Host, Origin-Realm, and Result-Code AVPs */ ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); ogs_assert(ret == 0); @@ -717,7 +704,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); - /* Get User-Data-Already-Available AVP (Mandatory has already been checked) */ + /* Get User-Data-Already-Available AVP (Mandatory) */ ret = fd_msg_search_avp(qry, ogs_diam_cx_user_data_already_available, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); @@ -727,7 +714,7 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, /* Nothing to do */ } else { /* Set the User-Data AVP */ - user_data = download_user_data(user_name, &subscription_data); + user_data = hss_cx_download_user_data(user_name, &ims_data); ogs_assert(user_data); ret = fd_msg_avp_new(ogs_diam_cx_user_data, 0, &avp); @@ -775,8 +762,6 @@ static int hss_ogs_diam_cx_sar_cb( struct msg **msg, struct avp *avp, ogs_diam_logger_self()->stats.nb_echoed++; ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - ogs_subscription_data_free(&subscription_data); - if (user_data) ogs_free(user_data); ogs_free(user_name); @@ -807,8 +792,6 @@ out: ret = fd_msg_send(msg, NULL, NULL); ogs_assert(ret == 0); - ogs_subscription_data_free(&subscription_data); - if (user_data) ogs_free(user_data); ogs_free(user_name); @@ -818,132 +801,117 @@ out: return 0; } -static char *download_user_data( - char *user_name, ogs_subscription_data_t *subscription_data) +/* Callback for incoming Location-Info-Request messages */ +static int hss_ogs_diam_cx_lir_cb( struct msg **msg, struct avp *avp, + struct session *session, void *opaque, enum disp_action *act) { - char *user_data = NULL; - int i; + int ret; + uint32_t result_code = 0; - ogs_assert(user_name); - ogs_assert(subscription_data); + struct msg *ans, *qry; - user_data = ogs_strdup(ogs_diam_cx_xml_version); - ogs_assert(user_data); + struct avp_hdr *hdr; + union avp_value val; - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_ims_subscription_s); - ogs_assert(user_data); + char *public_identity = NULL; + char *server_name = NULL; - user_data = ogs_mstrcatf(user_data, "%s%s%s", - ogs_diam_cx_xml_private_id_s, - user_name, - ogs_diam_cx_xml_private_id_e); - ogs_assert(user_data); + ogs_assert(msg); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_service_profile_s); - ogs_assert(user_data); + ogs_debug("Location-Info-Request"); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_s); - ogs_assert(user_data); + /* Create answer header */ + qry = *msg; + ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0); + ogs_assert(ret == 0); + ans = *msg; - user_data = ogs_mstrcatf(user_data, "%s%s%s", - ogs_diam_cx_xml_barring_indication_s, - "1", - ogs_diam_cx_xml_barring_indication_e); - ogs_assert(user_data); + /* Get Public-Identity AVP (Mandatory) */ + ret = fd_msg_search_avp(qry, ogs_diam_cx_public_identity, &avp); + ogs_assert(ret == 0); + ret = fd_msg_avp_hdr(avp, &hdr); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%ssip:%s%s", - ogs_diam_cx_xml_identity_s, - user_name, - ogs_diam_cx_xml_identity_e); - ogs_assert(user_data); + public_identity = ogs_strndup( + (char*)hdr->avp_value->os.data, hdr->avp_value->os.len); + ogs_assert(public_identity); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_s); - ogs_assert(user_data); + /* Get Server-Name by IMPU(Public-Identity) */ + server_name = hss_cx_get_server_name(public_identity); + if (!server_name) { + ogs_error("No Server-Name in Public-Identity[%s]", public_identity); + result_code = OGS_DIAM_CX_SERVER_NAME_NOT_STORED; + goto out; + } - user_data = ogs_mstrcatf(user_data, "%s%s%s", - ogs_diam_cx_xml_identity_type_s, - "0", - ogs_diam_cx_xml_identity_type_e); - ogs_assert(user_data); + /* Set Vendor-Specific-Application-Id AVP */ + ret = ogs_diam_message_vendor_specific_appid_set( + ans, OGS_DIAM_CX_APPLICATION_ID); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_e); - ogs_assert(user_data); + /* Set the Auth-Session-State AVP */ + ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 1; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_e); - ogs_assert(user_data); + /* Set the Origin-Host, Origin-Realm, and Result-Code AVPs */ + ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); + ogs_assert(ret == 0); - for (i = 0; i < subscription_data->num_of_msisdn; i++) { - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_s); - ogs_assert(user_data); + /* Set Server-Name AVPs */ + ret = fd_msg_avp_new(ogs_diam_cx_server_name, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (uint8_t *)server_name; + val.os.len = strlen(server_name); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%stel:%s%s", - ogs_diam_cx_xml_identity_s, - subscription_data->msisdn[i].bcd, - ogs_diam_cx_xml_identity_e); - ogs_assert(user_data); + /* Send the answer */ + ret = fd_msg_send(msg, NULL, NULL); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_s); - ogs_assert(user_data); + ogs_debug("Location-Info-Answer"); - user_data = ogs_mstrcatf(user_data, "%s%s%s", - ogs_diam_cx_xml_identity_type_s, - "0", - ogs_diam_cx_xml_identity_type_e); - ogs_assert(user_data); + /* Add this value to the stats */ + ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); + ogs_diam_logger_self()->stats.nb_echoed++; + ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_e); - ogs_assert(user_data); + ogs_free(public_identity); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_e); - ogs_assert(user_data); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_s); - ogs_assert(user_data); + return 0; - user_data = ogs_mstrcatf(user_data, "%ssip:%s%s", - ogs_diam_cx_xml_identity_s, - subscription_data->msisdn[i].bcd, - ogs_diam_cx_xml_identity_e); - ogs_assert(user_data); +out: + /* Set Vendor-Specific-Application-Id AVP */ + ret = ogs_diam_message_vendor_specific_appid_set( + ans, OGS_DIAM_CX_APPLICATION_ID); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_s); - ogs_assert(user_data); + /* Set the Experimental-Result, Origin-Host and Origin-Realm AVPs */ + ret = ogs_diam_message_experimental_rescode_set(ans, result_code); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s%s%s", - ogs_diam_cx_xml_identity_type_s, - "0", - ogs_diam_cx_xml_identity_type_e); - ogs_assert(user_data); + /* Set the Auth-Session-State AVP */ + ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 1; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_extension_e); - ogs_assert(user_data); + ret = fd_msg_send(msg, NULL, NULL); + ogs_assert(ret == 0); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_public_id_e); - ogs_assert(user_data); - } + ogs_free(public_identity); - user_data = ogs_mstrcatf(user_data, "%s", - ogs_diam_cx_xml_service_profile_e); - ogs_assert(user_data); - - user_data = ogs_mstrcatf(user_data, - "%s", ogs_diam_cx_xml_ims_subscription_e); - ogs_assert(user_data); - - return user_data; + return 0; } int hss_cx_init(void) @@ -981,6 +949,12 @@ int hss_cx_init(void) &hdl_cx_sar); ogs_assert(ret == 0); + /* Specific handler for Location-Info-Request */ + data.command = ogs_diam_cx_cmd_lir; + ret = fd_disp_register(hss_ogs_diam_cx_lir_cb, DISP_HOW_CC, &data, NULL, + &hdl_cx_lir); + ogs_assert(ret == 0); + /* Advertise the support for the application in the peer */ ret = fd_disp_app_support(ogs_diam_cx_application, ogs_diam_vendor, 1, 0); ogs_assert(ret == 0); @@ -998,4 +972,6 @@ void hss_cx_final(void) (void) fd_disp_unregister(&hdl_cx_mar, NULL); if (hdl_cx_sar) (void) fd_disp_unregister(&hdl_cx_sar, NULL); + if (hdl_cx_lir) + (void) fd_disp_unregister(&hdl_cx_lir, NULL); } diff --git a/tests/app/epc-init.c b/tests/app/epc-init.c index c84f0ffe2..27a417435 100644 --- a/tests/app/epc-init.c +++ b/tests/app/epc-init.c @@ -70,7 +70,7 @@ int app_initialize(const char *const argv[]) * * Note that at least 4 seconds are needed if freeDiameter is running. */ - ogs_msleep(5000); + ogs_msleep(500); return OGS_OK;; } diff --git a/tests/volte/abts-main.c b/tests/volte/abts-main.c index 10bf4051a..43f1401a5 100644 --- a/tests/volte/abts-main.c +++ b/tests/volte/abts-main.c @@ -19,7 +19,7 @@ #include "test-app.h" -#include "pcscf-fd-path.h" +#include "test-fd-path.h" abts_suite *test_bearer(abts_suite *suite); abts_suite *test_session(abts_suite *suite); @@ -45,7 +45,7 @@ static void terminate(void) test_child_terminate(); app_terminate(); - pcscf_fd_final(); + test_fd_final(); test_epc_final(); ogs_app_terminate(); @@ -59,7 +59,7 @@ static void initialize(const char *const argv[]) ogs_assert(rv == OGS_OK); test_epc_init(); - rv = pcscf_fd_init(); + rv = test_fd_init(); ogs_assert(rv == OGS_OK); rv = app_initialize(argv); diff --git a/tests/volte/cx-test.c b/tests/volte/cx-test.c index bce550667..cc21e19a1 100644 --- a/tests/volte/cx-test.c +++ b/tests/volte/cx-test.c @@ -18,7 +18,7 @@ */ #include "test-common.h" -#include "pcscf-fd-path.h" +#include "test-fd-path.h" static void test1_func(abts_case *tc, void *data) { @@ -265,7 +265,7 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive E-RAB Setup Request + diff --git a/tests/volte/diameter-cx-path.c b/tests/volte/diameter-cx-path.c index 4183f973a..4bb51d8b9 100644 --- a/tests/volte/diameter-cx-path.c +++ b/tests/volte/diameter-cx-path.c @@ -20,7 +20,7 @@ #include "ogs-diameter-cx.h" #include "test-common.h" -#include "pcscf-fd-path.h" +#include "test-fd-path.h" static struct session_handler *test_cx_reg = NULL; @@ -45,6 +45,9 @@ static void test_cx_maa_cb(void *data, struct msg **msg); static void test_cx_send_sar(struct sess_state *sess_data); static void test_cx_saa_cb(void *data, struct msg **msg); +static void test_cx_send_lir(struct sess_state *sess_data); +static void test_cx_lia_cb(void *data, struct msg **msg); + static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) { if (sess_data->user_name) @@ -882,6 +885,231 @@ static void test_cx_saa_cb(void *data, struct msg **msg) ogs_assert(ret == 0); *msg = NULL; + test_cx_send_lir(sess_data); + return; +} + +static void test_cx_send_lir(struct sess_state *sess_data) +{ + int ret; + + struct msg *req = NULL; + + struct msg_hdr *msg_header = NULL; + + struct session *session = NULL; + struct sess_state *svg; + + struct avp *avp = NULL, *avpch = NULL; + union avp_value val; + + test_ue_t *test_ue = NULL; + char *public_identity = NULL; + + ogs_assert(sess_data); + test_ue = sess_data->test_ue; + ogs_assert(test_ue); + + ogs_debug("Location-Info-Request"); + + /* Create the request */ + ret = fd_msg_new(ogs_diam_cx_cmd_lir, MSGFL_ALLOC_ETEID, &req); + ogs_assert(ret == 0); + + ret = fd_msg_hdr(req, &msg_header); + ogs_assert(ret == 0); + msg_header->msg_appl = OGS_DIAM_CX_APPLICATION_ID; + + #define OGS_DIAM_CX_APP_SID_OPT "app_cx" + ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_CX_APP_SID_OPT, + CONSTSTRLEN(OGS_DIAM_CX_APP_SID_OPT)); + ogs_assert(ret == 0); + ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL); + ogs_assert(ret == 0); + + /* Set Vendor-Specific-Application-Id AVP */ + ret = ogs_diam_message_vendor_specific_appid_set( + req, OGS_DIAM_CX_APPLICATION_ID); + ogs_assert(ret == 0); + + /* Set the Auth-Session-State AVP */ + ret = fd_msg_avp_new(ogs_diam_auth_session_state, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 1; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set Origin-Host & Origin-Realm */ + ret = fd_msg_add_origin(req, 0); + ogs_assert(ret == 0); + + /* Set the Destination-Host AVP */ + ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp); + ogs_assert(ret == 0); + val.os.data = TEST_HSS_IDENTITY; + val.os.len = strlen(TEST_HSS_IDENTITY); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Destination-Realm AVP */ + ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm); + val.os.len = strlen(fd_g_config->cnf_diamrlm); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Public-Identity AVP */ + ret = fd_msg_avp_new(ogs_diam_cx_public_identity, 0, &avp); + ogs_assert(ret == 0); + public_identity = ogs_msprintf("tel:%s", TEST_ADDITIONAL_MSISDN); + ogs_assert(public_identity); + val.os.data = (uint8_t *)public_identity; + val.os.len = strlen(public_identity); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); + ogs_assert(ret == 0); + + /* Keep a pointer to the session data for debug purpose, + * in real life we would not need it */ + svg = sess_data; + + /* Store this value in the session */ + ret = fd_sess_state_store(test_cx_reg, session, &sess_data); + ogs_assert(ret == 0); + ogs_assert(sess_data == 0); + + /* Send the request */ + ret = fd_msg_send(&req, test_cx_lia_cb, svg); + ogs_assert(ret == 0); + + /* Increment the counter */ + ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); + ogs_diam_logger_self()->stats.nb_sent++; + ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); + + ogs_free(public_identity); +} + +/* Callback for incoming Location-Info-Answer messages */ +static void test_cx_lia_cb(void *data, struct msg **msg) +{ + int ret, new; + + struct avp *avp, *avpch; + struct avp_hdr *hdr; + + unsigned long dur; + int error = 0; + + struct sess_state *sess_data = NULL; + struct timespec ts; + struct session *session; + + test_ue_t *test_ue = NULL; + + uint32_t result_code; + uint32_t *err = NULL, *exp_err = NULL; + + ogs_debug("Location-Info-Answer"); + + ret = clock_gettime(CLOCK_REALTIME, &ts); + ogs_assert(ret == 0); + + /* Search the session, retrieve its data */ + ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new); + ogs_expect_or_return(ret == 0); + ogs_expect_or_return(new == 0); + + ret = fd_sess_state_retrieve(test_cx_reg, session, &sess_data); + ogs_expect_or_return(ret == 0); + ogs_expect_or_return(sess_data); + ogs_expect_or_return((void *)sess_data == data); + + test_ue = sess_data->test_ue; + ogs_assert(test_ue); + + /* Value of Result Code */ + ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); + ogs_assert(ret == 0); + if (avp) { + ret = fd_msg_avp_hdr(avp, &hdr); + ogs_assert(ret == 0); + result_code = hdr->avp_value->i32; + err = &result_code; + ogs_debug(" Result Code: %d", hdr->avp_value->i32); + } else { + ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp); + ogs_assert(ret == 0); + if (avp) { + ret = fd_avp_search_avp(avp, + ogs_diam_experimental_result_code, &avpch); + ogs_assert(ret == 0); + if (avpch) { + ret = fd_msg_avp_hdr(avpch, &hdr); + ogs_assert(ret == 0); + result_code = hdr->avp_value->i32; + exp_err = &result_code; + ogs_debug(" Experimental Result Code: %d", result_code); + } + } else { + ogs_error("no Result-Code"); + error++; + } + } + + ogs_assert(err && !exp_err && result_code == ER_DIAMETER_SUCCESS); + + /* Free the message */ + ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); + dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) + + ((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + if (ogs_diam_logger_self()->stats.nb_recv) { + /* Ponderate in the avg */ + ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg * + ogs_diam_logger_self()->stats.nb_recv + dur) / + (ogs_diam_logger_self()->stats.nb_recv + 1); + /* Min, max */ + if (dur < ogs_diam_logger_self()->stats.shortest) + ogs_diam_logger_self()->stats.shortest = dur; + if (dur > ogs_diam_logger_self()->stats.longest) + ogs_diam_logger_self()->stats.longest = dur; + } else { + ogs_diam_logger_self()->stats.shortest = dur; + ogs_diam_logger_self()->stats.longest = dur; + ogs_diam_logger_self()->stats.avg = dur; + } + if (error) + ogs_diam_logger_self()->stats.nb_errs++; + else + ogs_diam_logger_self()->stats.nb_recv++; + + ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); + + /* Display how long it took */ + if (ts.tv_nsec > sess_data->ts.tv_nsec) + ogs_trace("in %d.%06ld sec", + (int)(ts.tv_sec - sess_data->ts.tv_sec), + (long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + else + ogs_trace("in %d.%06ld sec", + (int)(ts.tv_sec + 1 - sess_data->ts.tv_sec), + (long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); + + ret = fd_msg_free(*msg); + ogs_assert(ret == 0); + *msg = NULL; + state_cleanup(sess_data, NULL, NULL); return; } diff --git a/tests/volte/pcscf-fd-path.c b/tests/volte/diameter-rx-path.c similarity index 97% rename from tests/volte/pcscf-fd-path.c rename to tests/volte/diameter-rx-path.c index be424f828..58d711f1a 100644 --- a/tests/volte/pcscf-fd-path.c +++ b/tests/volte/diameter-rx-path.c @@ -21,9 +21,7 @@ #include "ogs-diameter-rx.h" #include "test-common.h" -#include "pcscf-fd-path.h" - -#define MAX_NUM_SESSION_STATE 32 +#include "test-fd-path.h" static struct session_handler *pcscf_rx_reg = NULL; static struct disp_hdl *hdl_rx_fb = NULL; @@ -67,7 +65,7 @@ static int pcscf_rx_fb_cb(struct msg **msg, struct avp *avp, return ENOTSUP; } -void pcscf_rx_send_aar_audio(uint8_t **rx_sid, +void test_rx_send_aar_audio(uint8_t **rx_sid, test_sess_t *sess, int id_type, int qos_type, int flow_type) { int rv; @@ -565,7 +563,7 @@ void pcscf_rx_send_aar_audio(uint8_t **rx_sid, ogs_free(sip_uri); } -void pcscf_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type) +void test_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type) { int rv; int ret; @@ -1243,7 +1241,7 @@ void pcscf_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type) ogs_free(sip_uri); } -void pcscf_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type) +void test_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type) { int rv; int ret; @@ -1860,12 +1858,12 @@ static int pcscf_rx_asr_cb( struct msg **msg, struct avp *avp, ogs_diam_logger_self()->stats.nb_echoed++; ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - pcscf_rx_send_str(sid); + test_rx_send_str(sid); return 0; } -void pcscf_rx_send_str(uint8_t *rx_sid) +void test_rx_send_str(uint8_t *rx_sid) { int rv; int ret; @@ -2099,58 +2097,11 @@ out: return; } -void pcscf_diam_config(void) -{ - memset(&diam_config, 0, sizeof(ogs_diam_config_t)); - - diam_config.cnf_diamid = "ims.localdomain"; - diam_config.cnf_diamrlm = "localdomain"; - diam_config.cnf_port = DIAMETER_PORT; - diam_config.cnf_port_tls = DIAMETER_SECURE_PORT; - diam_config.cnf_flags.no_sctp = 1; - diam_config.cnf_addr = "127.0.0.1"; - - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dbg_msg_dumps.fdx"; - diam_config.ext[diam_config.num_of_ext].conf = "0x8888"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_rfc5777.fdx"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_mip6i.fdx"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_nasreq.fdx"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_nas_mipv6.fdx"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_dcca.fdx"; - diam_config.num_of_ext++; - diam_config.ext[diam_config.num_of_ext].module = - FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_dcca_3gpp.fdx"; - diam_config.num_of_ext++; - - diam_config.conn[diam_config.num_of_conn].identity = TEST_HSS_IDENTITY; - diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.8"; - diam_config.num_of_conn++; - diam_config.conn[diam_config.num_of_conn].identity = TEST_PCRF_IDENTITY; - diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.9"; - diam_config.num_of_conn++; -} - -int pcscf_fd_init(void) +int test_rx_init(void) { int ret; struct disp_when data; - pcscf_diam_config(); - - ret = ogs_diam_init(FD_MODE_CLIENT, NULL, &diam_config); - ogs_assert(ret == 0); - test_cx_init(); /* Install objects definitions for this application */ @@ -2182,9 +2133,10 @@ int pcscf_fd_init(void) return 0; } -void pcscf_fd_final(void) +void test_rx_final(void) { int ret; + ret = fd_sess_handler_destroy(&pcscf_rx_reg, NULL); ogs_assert(ret == 0); @@ -2192,8 +2144,4 @@ void pcscf_fd_final(void) (void) fd_disp_unregister(&hdl_rx_fb, NULL); if (hdl_rx_asr) (void) fd_disp_unregister(&hdl_rx_asr, NULL); - - test_cx_final(); - - ogs_diam_final(); } diff --git a/tests/volte/meson.build b/tests/volte/meson.build index c014a9b4d..bb6436ee8 100644 --- a/tests/volte/meson.build +++ b/tests/volte/meson.build @@ -16,8 +16,9 @@ # along with this program. If not, see . testapp_volte_sources = files(''' - pcscf-fd-path.h - pcscf-fd-path.c + test-fd-path.h + test-fd-path.c + diameter-rx-path.c diameter-cx-path.c abts-main.c diff --git a/tests/volte/rx-test.c b/tests/volte/rx-test.c index d66b23ee8..13d50531d 100644 --- a/tests/volte/rx-test.c +++ b/tests/volte/rx-test.c @@ -18,7 +18,7 @@ */ #include "test-common.h" -#include "pcscf-fd-path.h" +#include "test-fd-path.h" static void test1_func(abts_case *tc, void *data) { @@ -263,7 +263,7 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive E-RABSetupRequest + @@ -304,7 +304,7 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request without Flow */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 2, 1); /* Receive E-RABModifyRequest + @@ -460,7 +460,7 @@ static void test1_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -787,7 +787,7 @@ static void test2_func(abts_case *tc, void *data) ogs_msleep(100); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 0, 1); /* Receive E-RABSetupRequest + @@ -1121,14 +1121,14 @@ static void test3_func(abts_case *tc, void *data) ogs_msleep(100); /* Send AA-Request */ - pcscf_rx_send_aar_ctrl(&rx_sid, sess, + test_rx_send_aar_ctrl(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* DELAY is needed for receiving AA-Answer */ ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* DELAY is needed for receiving Session-Termination-Answer */ ogs_msleep(100); @@ -1582,7 +1582,7 @@ static void test4_func(abts_case *tc, void *data) /* Send AA-Request */ sess = test_sess_find_by_apn(test_ue, "ims"); ogs_assert(sess); - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive E-RABSetupRequest + @@ -1613,7 +1613,7 @@ static void test4_func(abts_case *tc, void *data) /* DELAY is needed in dedicated EPS bearer */ ogs_msleep(100); - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -2048,7 +2048,7 @@ static void test5_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive S1-Paging */ @@ -2132,7 +2132,7 @@ static void test5_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send AA-Request without Flow */ - pcscf_rx_send_aar_audio(&rx_sid, sess, + test_rx_send_aar_audio(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 2, 1); /* Receive S1-Paging */ @@ -2204,7 +2204,7 @@ static void test5_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive S1-Paging */ recvbuf = testenb_s1ap_read(s1ap); @@ -2535,7 +2535,7 @@ static void test6_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid1, sess, + test_rx_send_aar_audio(&rx_sid1, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive E-RABSetupRequest + @@ -2576,7 +2576,7 @@ static void test6_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request */ - pcscf_rx_send_aar_audio(&rx_sid2, sess, + test_rx_send_aar_audio(&rx_sid2, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 2); /* Receive E-RABSetupRequest + @@ -2605,7 +2605,7 @@ static void test6_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid1); + test_rx_send_str(rx_sid1); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -2636,7 +2636,7 @@ static void test6_func(abts_case *tc, void *data) test_bearer_remove(bearer); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid2); + test_rx_send_str(rx_sid2); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ diff --git a/tests/volte/test-fd-path.c b/tests/volte/test-fd-path.c new file mode 100644 index 000000000..1267bd5be --- /dev/null +++ b/tests/volte/test-fd-path.c @@ -0,0 +1,89 @@ +/* + * 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 . + */ + +#include "test-common.h" +#include "test-fd-path.h" + +static ogs_diam_config_t diam_config; + +static void test_diam_config(void) +{ + memset(&diam_config, 0, sizeof(ogs_diam_config_t)); + + diam_config.cnf_diamid = "ims.localdomain"; + diam_config.cnf_diamrlm = "localdomain"; + diam_config.cnf_port = DIAMETER_PORT; + diam_config.cnf_port_tls = DIAMETER_SECURE_PORT; + diam_config.cnf_flags.no_sctp = 1; + diam_config.cnf_addr = "127.0.0.1"; + + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dbg_msg_dumps.fdx"; + diam_config.ext[diam_config.num_of_ext].conf = "0x8888"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_rfc5777.fdx"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_mip6i.fdx"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_nasreq.fdx"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_nas_mipv6.fdx"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_dcca.fdx"; + diam_config.num_of_ext++; + diam_config.ext[diam_config.num_of_ext].module = + FD_EXT_DIR OGS_DIR_SEPARATOR_S "dict_dcca_3gpp.fdx"; + diam_config.num_of_ext++; + + diam_config.conn[diam_config.num_of_conn].identity = TEST_HSS_IDENTITY; + diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.8"; + diam_config.num_of_conn++; + diam_config.conn[diam_config.num_of_conn].identity = TEST_PCRF_IDENTITY; + diam_config.conn[diam_config.num_of_conn].addr = "127.0.0.9"; + diam_config.num_of_conn++; +} + +int test_fd_init(void) +{ + int ret; + struct disp_when data; + + test_diam_config(); + + ret = ogs_diam_init(FD_MODE_CLIENT, NULL, &diam_config); + ogs_assert(ret == 0); + + test_rx_init(); + test_cx_init(); + + return 0; +} + +void test_fd_final(void) +{ + test_rx_final(); + test_cx_final(); + + ogs_diam_final(); +} diff --git a/tests/volte/pcscf-fd-path.h b/tests/volte/test-fd-path.h similarity index 73% rename from tests/volte/pcscf-fd-path.h rename to tests/volte/test-fd-path.h index d342fa789..2184ae055 100644 --- a/tests/volte/pcscf-fd-path.h +++ b/tests/volte/test-fd-path.h @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#ifndef PCSCF_FD_PATH_H -#define PCSCF_FD_PATH_H +#ifndef TEST_FD_PATH_H +#define TEST_FD_PATH_H #ifdef __cplusplus extern "C" { @@ -29,17 +29,20 @@ extern "C" { #define TEST_HSS_IDENTITY "hss.localdomain" #define TEST_PCRF_IDENTITY "pcrf.localdomain" -int pcscf_fd_init(void); -void pcscf_fd_final(void); +int test_fd_init(void); +void test_fd_final(void); + +int test_rx_init(void); +void test_rx_final(void); int test_cx_init(void); void test_cx_final(void); -void pcscf_rx_send_aar_audio(uint8_t **rx_sid, +void test_rx_send_aar_audio(uint8_t **rx_sid, test_sess_t *sess, int id_type, int qos_type, int flow_type); -void pcscf_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type); -void pcscf_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type); -void pcscf_rx_send_str(uint8_t *rx_sid); +void test_rx_send_aar_video(uint8_t **rx_sid, test_sess_t *sess, int id_type); +void test_rx_send_aar_ctrl(uint8_t **rx_sid, test_sess_t *sess, int id_type); +void test_rx_send_str(uint8_t *rx_sid); void test_cx_send_uar(test_ue_t *test_ue, int id_type); @@ -47,5 +50,5 @@ void test_cx_send_uar(test_ue_t *test_ue, int id_type); } #endif -#endif /* PCSCF_FD_PATH_H */ +#endif /* TEST_FD_PATH_H */ diff --git a/tests/volte/video-test.c b/tests/volte/video-test.c index 0aa9db469..07145a50b 100644 --- a/tests/volte/video-test.c +++ b/tests/volte/video-test.c @@ -18,7 +18,7 @@ */ #include "test-common.h" -#include "pcscf-fd-path.h" +#include "test-fd-path.h" static void test1_func(abts_case *tc, void *data) { @@ -262,7 +262,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -387,7 +387,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -424,7 +424,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -549,7 +549,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -586,7 +586,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -711,7 +711,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -748,7 +748,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -873,7 +873,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -910,7 +910,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -1035,7 +1035,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */ @@ -1072,7 +1072,7 @@ static void test1_func(abts_case *tc, void *data) /* Send AA-Request */ rx_sid = NULL; - pcscf_rx_send_aar_video(&rx_sid, sess, + test_rx_send_aar_video(&rx_sid, sess, OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); /* Receive E-RABSetupRequest + @@ -1197,7 +1197,7 @@ static void test1_func(abts_case *tc, void *data) ogs_msleep(100); /* Send Session-Termination-Request */ - pcscf_rx_send_str(rx_sid); + test_rx_send_str(rx_sid); /* Receive E-RABReleaseCommand + * Dectivate EPS bearer context request */