2017-07-22 00:44:42 +00:00
|
|
|
#define TRACE_MODULE _hss_s6a_handler
|
|
|
|
|
|
|
|
#include "core_debug.h"
|
|
|
|
#include "core_lib.h"
|
|
|
|
#include "core_sha2.h"
|
|
|
|
|
2017-08-05 05:23:37 +00:00
|
|
|
#include "fd_lib.h"
|
2017-07-22 00:44:42 +00:00
|
|
|
#include "s6a_lib.h"
|
|
|
|
|
|
|
|
#include "hss_context.h"
|
|
|
|
#include "hss_kdf.h"
|
|
|
|
#include "milenage.h"
|
|
|
|
|
|
|
|
#define HSS_SQN_LEN 6
|
|
|
|
#define HSS_AK_LEN 6
|
|
|
|
|
|
|
|
/* handler for fallback cb */
|
|
|
|
static struct disp_hdl *hdl_fb = NULL;
|
|
|
|
/* handler for Authentication-Information-Request cb */
|
|
|
|
static struct disp_hdl *hdl_air = NULL;
|
|
|
|
/* handler for Update-Location-Request cb */
|
|
|
|
static struct disp_hdl *hdl_ulr = NULL;
|
|
|
|
|
|
|
|
/* Default callback for the application. */
|
|
|
|
static int hss_fb_cb(struct msg **msg, struct avp *avp,
|
2017-08-18 11:43:28 +00:00
|
|
|
struct session *session, void *opaque, enum disp_action *act)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
/* This CB should never be called */
|
|
|
|
d_warn("Unexpected message received!");
|
|
|
|
|
|
|
|
return ENOTSUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for incoming Authentication-Information-Request messages */
|
|
|
|
static int hss_air_cb( struct msg **msg, struct avp *avp,
|
2017-08-18 11:43:28 +00:00
|
|
|
struct session *session, void *opaque, enum disp_action *act)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
struct msg *ans, *qry;
|
|
|
|
struct avp *avp_e_utran_vector, *avp_xres, *avp_kasme, *avp_rand, *avp_autn;
|
|
|
|
struct avp_hdr *hdr;
|
|
|
|
union avp_value val;
|
|
|
|
|
|
|
|
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
|
|
|
|
c_uint8_t opc[HSS_KEY_LEN];
|
|
|
|
c_uint8_t sqn[HSS_SQN_LEN];
|
|
|
|
c_uint8_t autn[AUTN_LEN];
|
|
|
|
c_uint8_t ik[HSS_KEY_LEN];
|
|
|
|
c_uint8_t ck[HSS_KEY_LEN];
|
|
|
|
c_uint8_t ak[HSS_AK_LEN];
|
|
|
|
c_uint8_t xres[MAX_RES_LEN];
|
|
|
|
c_uint8_t kasme[SHA256_DIGEST_SIZE];
|
|
|
|
size_t xres_len = 8;
|
|
|
|
|
|
|
|
hss_db_auth_info_t auth_info;
|
|
|
|
c_uint8_t zero[RAND_LEN];
|
|
|
|
status_t rv;
|
2017-08-09 05:48:44 +00:00
|
|
|
c_uint32_t result_code = 0;
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
d_assert(msg, return EINVAL,);
|
|
|
|
|
|
|
|
/* Create answer header */
|
|
|
|
qry = *msg;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0) );
|
2017-07-22 00:44:42 +00:00
|
|
|
ans = *msg;
|
|
|
|
|
2017-08-08 14:45:11 +00:00
|
|
|
CHECK_FCT( fd_msg_search_avp(qry, fd_user_name, &avp) );
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) );
|
2017-08-19 07:49:44 +00:00
|
|
|
core_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
|
|
|
c_min(hdr->avp_value->os.len, MAX_IMSI_BCD_LEN)+1);
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
rv = hss_db_auth_info(imsi_bcd, &auth_info);
|
|
|
|
if (rv != CORE_OK)
|
|
|
|
{
|
2017-08-11 05:14:55 +00:00
|
|
|
d_trace(3, "Cannot get Auth-Info for IMSI:'%s'\n", imsi_bcd);
|
2017-08-09 05:48:44 +00:00
|
|
|
result_code = S6A_DIAMETER_ERROR_USER_UNKNOWN;
|
2017-07-22 00:44:42 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(zero, 0, sizeof(zero));
|
|
|
|
if (memcmp(auth_info.rand, zero, RAND_LEN) == 0)
|
|
|
|
{
|
|
|
|
core_generate_random_bytes(auth_info.rand, RAND_LEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = hss_db_update_rand_and_sqn(imsi_bcd, auth_info.rand, auth_info.sqn);
|
|
|
|
if (rv != CORE_OK)
|
|
|
|
{
|
|
|
|
d_error("Cannot update rand and sqn for IMSI:'%s'", imsi_bcd);
|
2017-08-09 05:48:44 +00:00
|
|
|
result_code = S6A_DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE;
|
2017-07-22 00:44:42 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = hss_db_increment_sqn(imsi_bcd);
|
|
|
|
if (rv != CORE_OK)
|
|
|
|
{
|
|
|
|
d_error("Cannot increment sqn for IMSI:'%s'", imsi_bcd);
|
2017-08-09 05:48:44 +00:00
|
|
|
result_code = S6A_DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE;
|
2017-07-22 00:44:42 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_search_avp(qry, s6a_visited_plmn_id, &avp) );
|
|
|
|
CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) );
|
2017-07-22 00:44:42 +00:00
|
|
|
#if 0 // TODO : check visited_plmn_id
|
2017-08-19 07:49:44 +00:00
|
|
|
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
2017-07-22 00:44:42 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
milenage_opc(auth_info.k, auth_info.op, opc);
|
|
|
|
milenage_generate(opc, auth_info.amf, auth_info.k,
|
|
|
|
core_uint64_to_buffer(auth_info.sqn, HSS_SQN_LEN, sqn), auth_info.rand,
|
|
|
|
autn, ik, ck, ak, xres, &xres_len);
|
|
|
|
hss_kdf_kasme(ck, ik, hdr->avp_value->os.data, sqn, ak, kasme);
|
|
|
|
|
|
|
|
/* Set the Authentication-Info */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_authentication_info, 0, &avp) );
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_e_utran_vector, 0, &avp_e_utran_vector) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_rand, 0, &avp_rand) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.os.data = auth_info.rand;
|
|
|
|
val.os.len = HSS_KEY_LEN;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_rand, &val) );
|
|
|
|
CHECK_FCT(
|
|
|
|
fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_rand) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_xres, 0, &avp_xres) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.os.data = xres;
|
|
|
|
val.os.len = xres_len;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_xres, &val) );
|
|
|
|
CHECK_FCT(
|
|
|
|
fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_xres) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_autn, 0, &avp_autn) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.os.data = autn;
|
|
|
|
val.os.len = AUTN_LEN;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_autn, &val) );
|
|
|
|
CHECK_FCT(
|
|
|
|
fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_autn) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_kasme, 0, &avp_kasme) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.os.data = kasme;
|
|
|
|
val.os.len = SHA256_DIGEST_SIZE;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_kasme, &val) );
|
|
|
|
CHECK_FCT(
|
|
|
|
fd_msg_avp_add(avp_e_utran_vector, MSG_BRW_LAST_CHILD, avp_kasme) );
|
|
|
|
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_e_utran_vector) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
2017-08-09 05:48:44 +00:00
|
|
|
|
|
|
|
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
|
|
|
CHECK_FCT( fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) );
|
|
|
|
|
|
|
|
/* Set the Auth-Session-State AVP */
|
|
|
|
CHECK_FCT( fd_msg_avp_new(fd_auth_session_state, 0, &avp) );
|
|
|
|
val.i32 = 1;
|
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
|
|
|
|
2017-07-22 00:44:42 +00:00
|
|
|
/* Send the answer */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_send(msg, NULL, NULL) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Add this value to the stats */
|
2017-08-17 00:43:33 +00:00
|
|
|
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
|
|
|
fd_logger_self()->stats.nb_echoed++;
|
|
|
|
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out:
|
2017-08-09 05:48:44 +00:00
|
|
|
CHECK_FCT( fd_message_experimental_rescode_set(ans, result_code) );
|
2017-08-16 13:03:36 +00:00
|
|
|
|
|
|
|
/* Set the Auth-Session-State AVP */
|
|
|
|
CHECK_FCT( fd_msg_avp_new(fd_auth_session_state, 0, &avp) );
|
|
|
|
val.i32 = 1;
|
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_send(msg, NULL, NULL) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Callback for incoming Update-Location-Request messages */
|
|
|
|
static int hss_ulr_cb( struct msg **msg, struct avp *avp,
|
2017-08-18 11:43:28 +00:00
|
|
|
struct session *session, void *opaque, enum disp_action *act)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
struct msg *ans, *qry;
|
|
|
|
|
|
|
|
struct avp_hdr *hdr;
|
|
|
|
union avp_value val;
|
|
|
|
|
|
|
|
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
|
|
|
|
|
|
|
|
status_t rv;
|
|
|
|
hss_db_subscription_data_t subscription_data;
|
|
|
|
|
|
|
|
d_assert(msg, return EINVAL,);
|
|
|
|
|
|
|
|
/* Create answer header */
|
|
|
|
qry = *msg;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0) );
|
2017-07-22 00:44:42 +00:00
|
|
|
ans = *msg;
|
|
|
|
|
2017-08-08 14:45:11 +00:00
|
|
|
CHECK_FCT( fd_msg_search_avp(qry, fd_user_name, &avp) );
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) );
|
2017-08-19 07:49:44 +00:00
|
|
|
core_cpystrn(imsi_bcd, (char*)hdr->avp_value->os.data,
|
|
|
|
c_min(hdr->avp_value->os.len, MAX_IMSI_BCD_LEN)+1);
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
rv = hss_db_subscription_data(imsi_bcd, &subscription_data);
|
|
|
|
if (rv != CORE_OK)
|
|
|
|
{
|
|
|
|
d_error("Cannot get Subscription-Data for IMSI:'%s'", imsi_bcd);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_search_avp(qry, s6a_visited_plmn_id, &avp) );
|
|
|
|
CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) );
|
2017-07-22 00:44:42 +00:00
|
|
|
#if 0 // TODO : check visited_plmn_id
|
2017-08-19 07:49:44 +00:00
|
|
|
memcpy(visited_plmn_id, hdr->avp_value->os.data, hdr->avp_value->os.len);
|
2017-07-22 00:44:42 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set the Auth-Session-Statee AVP */
|
2017-08-08 14:45:11 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(fd_auth_session_state, 0, &avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = 1;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set the ULA Flags */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_ula_flags, 0, &avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = S6A_ULA_MME_REGISTERED_FOR_SMS;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
|
|
|
|
|
|
|
CHECK_FCT( fd_msg_search_avp(qry, s6a_ulr_flags, &avp) );
|
|
|
|
CHECK_FCT( fd_msg_avp_hdr(avp, &hdr) );
|
|
|
|
if (!(hdr->avp_value->u32 & S6A_ULR_SKIP_SUBSCRIBER_DATA))
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
2017-08-16 13:03:36 +00:00
|
|
|
struct avp *avp_access_restriction_data;
|
2017-07-22 00:44:42 +00:00
|
|
|
struct avp *avp_subscriber_status, *avp_network_access_mode;
|
|
|
|
struct avp *avp_ambr, *avp_max_bandwidth_ul, *avp_max_bandwidth_dl;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Set the Subscription Data */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_subscription_data, 0, &avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
if (subscription_data.access_restriction_data)
|
|
|
|
{
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_access_restriction_data, 0,
|
|
|
|
&avp_access_restriction_data) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = subscription_data.access_restriction_data;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(
|
|
|
|
avp_access_restriction_data, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_access_restriction_data) );
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_subscriber_status, 0,
|
|
|
|
&avp_subscriber_status) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = subscription_data.subscriber_status;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_subscriber_status, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_subscriber_status) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_network_access_mode, 0,
|
|
|
|
&avp_network_access_mode) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = subscription_data.network_access_mode;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_network_access_mode, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_network_access_mode) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set the AMBR */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_ambr, 0, &avp_ambr) );
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_max_bandwidth_ul, 0,
|
|
|
|
&avp_max_bandwidth_ul) );
|
|
|
|
/* bits per second */
|
|
|
|
val.i32 = subscription_data.max_bandwidth_ul * 1024;
|
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_max_bandwidth_ul) );
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_max_bandwidth_dl, 0,
|
|
|
|
&avp_max_bandwidth_dl) );
|
|
|
|
/* bits per second */
|
|
|
|
val.i32 = subscription_data.max_bandwidth_dl * 1024;
|
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_max_bandwidth_dl) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avp_ambr) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-11 08:16:35 +00:00
|
|
|
if (subscription_data.num_of_pdn)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
/* Set the APN Configuration Profile */
|
|
|
|
struct avp *apn_configuration_profile;
|
2017-08-16 13:03:36 +00:00
|
|
|
struct avp *context_identifier;
|
|
|
|
struct avp *all_apn_configuration_included_indicator;
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_apn_configuration_profile, 0,
|
|
|
|
&apn_configuration_profile) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_context_identifier, 0,
|
|
|
|
&context_identifier) );
|
2017-08-19 07:49:44 +00:00
|
|
|
val.i32 = 0;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(context_identifier, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration_profile,
|
|
|
|
MSG_BRW_LAST_CHILD, context_identifier) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-16 13:03:36 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(
|
|
|
|
s6a_all_apn_configuration_included_indicator, 0,
|
|
|
|
&all_apn_configuration_included_indicator) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = 0;
|
2017-08-16 13:03:36 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(
|
|
|
|
all_apn_configuration_included_indicator, &val) );
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration_profile,
|
2017-08-16 13:03:36 +00:00
|
|
|
MSG_BRW_LAST_CHILD,
|
|
|
|
all_apn_configuration_included_indicator) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-11 08:16:35 +00:00
|
|
|
for (i = 0; i < subscription_data.num_of_pdn; i++)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
/* Set the APN Configuration */
|
|
|
|
struct avp *apn_configuration, *context_identifier;
|
|
|
|
struct avp *pdn_type, *service_selection;
|
|
|
|
struct avp *eps_subscribed_qos_profile, *qos_class_identifier;
|
|
|
|
struct avp *allocation_retention_priority, *priority_level;
|
|
|
|
struct avp *pre_emption_capability, *pre_emption_vulnerability;
|
|
|
|
|
2017-08-11 10:34:27 +00:00
|
|
|
pdn_t *pdn = &subscription_data.pdn[i];
|
2017-08-11 08:16:35 +00:00
|
|
|
d_assert(pdn, goto out,);
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_apn_configuration, 0,
|
|
|
|
&apn_configuration) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_context_identifier, 0,
|
|
|
|
&context_identifier) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.i32 = pdn->context_identifier;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(context_identifier, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration,
|
|
|
|
MSG_BRW_LAST_CHILD, context_identifier) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_pdn_type, 0, &pdn_type) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.i32 = pdn->pdn_type;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(pdn_type, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration,
|
|
|
|
MSG_BRW_LAST_CHILD, pdn_type) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_service_selection, 0,
|
|
|
|
&service_selection) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.os.data = (c_uint8_t *)pdn->apn;
|
|
|
|
val.os.len = strlen(pdn->apn);
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(service_selection, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration,
|
|
|
|
MSG_BRW_LAST_CHILD, service_selection) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set the EPS Subscribed QoS Profile */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_eps_subscribed_qos_profile, 0,
|
|
|
|
&eps_subscribed_qos_profile) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_qos_class_identifier, 0,
|
|
|
|
&qos_class_identifier) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.i32 = pdn->qos.qci;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(qos_class_identifier, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(eps_subscribed_qos_profile,
|
|
|
|
MSG_BRW_LAST_CHILD, qos_class_identifier) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set Allocation retention priority */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_allocation_retention_priority, 0,
|
|
|
|
&allocation_retention_priority) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_priority_level, 0,
|
|
|
|
&priority_level) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.u32 = pdn->qos.priority_level;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(priority_level, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(allocation_retention_priority,
|
|
|
|
MSG_BRW_LAST_CHILD, priority_level) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_pre_emption_capability, 0,
|
|
|
|
&pre_emption_capability) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.u32 = pdn->qos.pre_emption_capability;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(pre_emption_capability, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(allocation_retention_priority,
|
|
|
|
MSG_BRW_LAST_CHILD, pre_emption_capability) );
|
|
|
|
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_pre_emption_vulnerability, 0,
|
|
|
|
&pre_emption_vulnerability) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.u32 = pdn->qos.pre_emption_vulnerability;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT(
|
|
|
|
fd_msg_avp_setvalue(pre_emption_vulnerability, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(allocation_retention_priority,
|
|
|
|
MSG_BRW_LAST_CHILD, pre_emption_vulnerability) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(eps_subscribed_qos_profile,
|
|
|
|
MSG_BRW_LAST_CHILD, allocation_retention_priority) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration,
|
|
|
|
MSG_BRW_LAST_CHILD, eps_subscribed_qos_profile) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Set AMBR */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_ambr, 0, &avp_ambr) );
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_max_bandwidth_ul, 0,
|
|
|
|
&avp_max_bandwidth_ul) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.i32 = pdn->qos.max_bandwidth_ul * 1024;/* bits per second */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_max_bandwidth_ul, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_max_bandwidth_ul) );
|
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_max_bandwidth_dl, 0,
|
|
|
|
&avp_max_bandwidth_dl) );
|
2017-08-11 08:16:35 +00:00
|
|
|
val.i32 = pdn->qos.max_bandwidth_dl * 1024;/* bits per second */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp_max_bandwidth_dl, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(avp_ambr, MSG_BRW_LAST_CHILD,
|
|
|
|
avp_max_bandwidth_dl) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration,
|
|
|
|
MSG_BRW_LAST_CHILD, avp_ambr) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(apn_configuration_profile,
|
|
|
|
MSG_BRW_LAST_CHILD, apn_configuration) );
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD,
|
|
|
|
apn_configuration_profile) );
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_new(s6a_subscribed_rau_tau_timer, 0, &avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
val.i32 = subscription_data.subscribed_rau_tau_timer * 60; /* seconds */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_avp_setvalue(avp, &val) );
|
|
|
|
CHECK_FCT( fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Send the answer */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_send(msg, NULL, NULL) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* Add this value to the stats */
|
2017-08-17 00:43:33 +00:00
|
|
|
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
|
|
|
fd_logger_self()->stats.nb_echoed++;
|
|
|
|
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out:
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_msg_rescode_set(
|
|
|
|
ans, "DIAMETER_AUTHENTICATION_REJECTED", NULL, NULL, 1) );
|
|
|
|
CHECK_FCT( fd_msg_send(msg, NULL, NULL) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
int hss_s6a_init(void)
|
2017-07-22 00:44:42 +00:00
|
|
|
{
|
|
|
|
struct disp_when data;
|
|
|
|
|
2017-08-17 00:43:33 +00:00
|
|
|
CHECK_FCT( fd_init(FD_MODE_SERVER, hss_self()->fd_conf_path) );
|
|
|
|
|
2017-08-05 05:23:37 +00:00
|
|
|
/* Install objects definitions for this application */
|
2017-08-05 07:07:52 +00:00
|
|
|
CHECK_FCT( s6a_dict_init() );
|
2017-08-05 05:23:37 +00:00
|
|
|
|
2017-07-22 00:44:42 +00:00
|
|
|
memset(&data, 0, sizeof(data));
|
2017-08-09 03:52:11 +00:00
|
|
|
data.app = s6a_application;
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* fallback CB if command != unexpected message received */
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_disp_register(hss_fb_cb, DISP_HOW_APPID, &data, NULL,
|
|
|
|
&hdl_fb) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* specific handler for Authentication-Information-Request */
|
|
|
|
data.command = s6a_cmd_air;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_disp_register(hss_air_cb, DISP_HOW_CC, &data, NULL,
|
|
|
|
&hdl_air) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
|
|
|
/* specific handler for Location-Update-Request */
|
|
|
|
data.command = s6a_cmd_ulr;
|
2017-08-05 08:57:29 +00:00
|
|
|
CHECK_FCT( fd_disp_register(hss_ulr_cb, DISP_HOW_CC, &data, NULL,
|
|
|
|
&hdl_ulr) );
|
2017-07-22 00:44:42 +00:00
|
|
|
|
2017-08-05 05:23:37 +00:00
|
|
|
/* Advertise the support for the application in the peer */
|
2017-08-16 13:03:36 +00:00
|
|
|
CHECK_FCT( fd_disp_app_support(s6a_application, fd_vendor, 1, 0) );
|
2017-08-05 05:23:37 +00:00
|
|
|
|
2017-08-05 08:57:29 +00:00
|
|
|
return 0;
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void hss_s6a_final(void)
|
|
|
|
{
|
|
|
|
if (hdl_fb) {
|
|
|
|
(void) fd_disp_unregister(&hdl_fb, NULL);
|
|
|
|
}
|
|
|
|
if (hdl_air) {
|
|
|
|
(void) fd_disp_unregister(&hdl_air, NULL);
|
|
|
|
}
|
|
|
|
if (hdl_ulr) {
|
|
|
|
(void) fd_disp_unregister(&hdl_ulr, NULL);
|
|
|
|
}
|
2017-08-17 00:43:33 +00:00
|
|
|
|
|
|
|
fd_final();
|
2017-07-22 00:44:42 +00:00
|
|
|
}
|