diff --git a/lib/diameter/gy/message.c b/lib/diameter/gy/message.c index 00585583b..920c36569 100644 --- a/lib/diameter/gy/message.c +++ b/lib/diameter/gy/message.c @@ -46,6 +46,14 @@ struct dict_object *ogs_diam_gy_cc_service_specific_units = NULL; struct dict_object *ogs_diam_gy_reporting_reason = NULL; struct dict_object *ogs_diam_gy_service_id = NULL; +struct dict_object *ogs_diam_gy_service_information = NULL; +struct dict_object *ogs_diam_gy_ps_information = NULL; +struct dict_object *ogs_diam_gy_3gpp_charging_id = NULL; +struct dict_object *ogs_diam_gy_3gpp_pdp_type = NULL; +struct dict_object *ogs_diam_gy_pdp_address = NULL; +struct dict_object *ogs_diam_gy_sgsn_address = NULL; +struct dict_object *ogs_diam_gy_ggsn_address = NULL; + struct dict_object *ogs_diam_gy_feature_list_id = NULL; struct dict_object *ogs_diam_gy_feature_list = NULL; struct dict_object *ogs_diam_gy_qos_information = NULL; @@ -98,6 +106,14 @@ int ogs_diam_gy_init(void) CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Reporting-Reason", &ogs_diam_gy_reporting_reason); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Service-Identifier", &ogs_diam_gy_service_id); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Service-Information", &ogs_diam_gy_service_information); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "PS-Information", &ogs_diam_gy_ps_information); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-Charging-Id", &ogs_diam_gy_3gpp_charging_id); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-PDP-Type", &ogs_diam_gy_3gpp_pdp_type); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "PDP-Address", &ogs_diam_gy_pdp_address); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "SGSN-Address", &ogs_diam_gy_sgsn_address); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "GGSN-Address", &ogs_diam_gy_ggsn_address); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List-ID", &ogs_diam_gy_feature_list_id); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List", &ogs_diam_gy_feature_list); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "QoS-Information", &ogs_diam_gy_qos_information); diff --git a/lib/diameter/gy/message.h b/lib/diameter/gy/message.h index dd9ce5ded..e08e1a73c 100644 --- a/lib/diameter/gy/message.h +++ b/lib/diameter/gy/message.h @@ -90,6 +90,20 @@ extern struct dict_object *ogs_diam_gy_reporting_reason; #define OGS_DIAM_GY_REPORTING_REASON_POOL_EXHAUSTED 8 #define OGS_DIAM_GY_REPORTING_REASON_UNUSED_QUOTA_TIMER 9 extern struct dict_object *ogs_diam_gy_service_id; +extern struct dict_object *ogs_diam_gy_service_information; +extern struct dict_object *ogs_diam_gy_ps_information; +extern struct dict_object *ogs_diam_gy_3gpp_charging_id; +extern struct dict_object *ogs_diam_gy_3gpp_pdp_type; +#define OGS_DIAM_GY_3GPP_PDP_TYPE_IPv4 0 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_PPP 1 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_IPv6 2 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_IPv4v6 3 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_NON_IP 4 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_UNSTRUCTURED 5 +#define OGS_DIAM_GY_3GPP_PDP_TYPE_ETHERNET 6 +extern struct dict_object *ogs_diam_gy_pdp_address; +extern struct dict_object *ogs_diam_gy_sgsn_address; +extern struct dict_object *ogs_diam_gy_ggsn_address; extern struct dict_object *ogs_diam_gy_feature_list_id; extern struct dict_object *ogs_diam_gy_feature_list; extern struct dict_object *ogs_diam_gy_qos_information; diff --git a/src/smf/gy-path.c b/src/smf/gy-path.c index d3cad2864..c2cd79002 100644 --- a/src/smf/gy-path.c +++ b/src/smf/gy-path.c @@ -244,6 +244,205 @@ static void fill_multiple_services_credit_control_ccr(smf_sess_t *sess, ogs_assert(ret == 0); } +/* TS 32.299 7.2.192 Service-Information AVP for CCR */ +static void fill_service_information_ccr(smf_sess_t *sess, + uint32_t cc_request_type, struct msg *req) +{ + int ret; + union avp_value val; + struct avp *avp; + struct avp *avpch1, *avpch2; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + char buf[OGS_PLMNIDSTRLEN]; + + /* Service-Information, TS 32.299 sec 7.2.192 */ + ret = fd_msg_avp_new(ogs_diam_gy_service_information, 0, &avp); + + /* PS-Information, TS 32.299 sec 7.2.158 */ + ret = fd_msg_avp_new(ogs_diam_gy_ps_information, 0, &avpch1); + + /* 3GPP-Charging-Id, 3GPP TS 29.061 16.4.7.2 2 */ + ret = fd_msg_avp_new(ogs_diam_gy_3gpp_charging_id, 0, &avpch2); + ogs_assert(ret == 0); + val.u32 = sess->charging.id; + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + /* 3GPP-PDP-Type, 3GPP TS 29.061 16.4.7.2 3 */ + if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST) { + ret = fd_msg_avp_new(ogs_diam_gy_3gpp_pdp_type, 0, &avpch2); + ogs_assert(ret == 0); + switch (sess->session.session_type) { + case OGS_PDU_SESSION_TYPE_IPV4: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_IPv4; + break; + case OGS_PDU_SESSION_TYPE_IPV6: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_IPv6; + break; + case OGS_PDU_SESSION_TYPE_IPV4V6: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_IPv4v6; + break; + case OGS_PDU_SESSION_TYPE_UNSTRUCTURED: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_UNSTRUCTURED; + break; + case OGS_PDU_SESSION_TYPE_ETHERNET: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_ETHERNET; + break; + default: + val.i32 = OGS_DIAM_GY_3GPP_PDP_TYPE_NON_IP; + } + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + + /* PDP-Address, TS 32.299 7.2.137 */ + if (sess->ipv4) { + ret = fd_msg_avp_new(ogs_diam_gy_pdp_address, 0, &avpch2); + sin.sin_family = AF_INET; + memcpy(&sin.sin_addr.s_addr, (uint8_t*)&sess->ipv4->addr[0], OGS_IPV4_LEN); + ret = fd_msg_avp_value_encode(&sin, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + } + if (sess->ipv6) { + ret = fd_msg_avp_new(ogs_diam_gy_pdp_address, 0, &avpch2); + sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr.s6_addr, (uint8_t*)&sess->ipv6->addr[0], OGS_IPV6_LEN); + ret = fd_msg_avp_value_encode(&sin6, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + /* PDP-Address-Prefix-Length, TS 32.299 7.2.137 */ + /* TODO: not yet needed since used OGS_IPV6_DEFAULT_PREFIX_LEN is 64. + if (OGS_IPV6_DEFAULT_PREFIX_LEN != 64) { + .u32 = sess->ipv6->subnet->prefixlen; + } + */ + } + + /* SGSN-Address */ + if (sess->sgw_s5c_ip.ipv4) { + ret = fd_msg_avp_new(ogs_diam_gy_sgsn_address, 0, &avpch2); + sin.sin_family = AF_INET; + memcpy(&sin.sin_addr.s_addr, (uint8_t*)&sess->sgw_s5c_ip.addr, OGS_IPV4_LEN); + ret = fd_msg_avp_value_encode(&sin, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + if (sess->sgw_s5c_ip.ipv6) { + ret = fd_msg_avp_new(ogs_diam_gy_sgsn_address, 0, &avpch2); + sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr.s6_addr, (uint8_t*)&sess->sgw_s5c_ip.addr6[0], OGS_IPV6_LEN); + ret = fd_msg_avp_value_encode(&sin6, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + + /* GGSN-Address */ + if (ogs_gtp_self()->gtpc_addr) { + ret = fd_msg_avp_new(ogs_diam_gy_ggsn_address, 0, &avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_value_encode(&ogs_gtp_self()->gtpc_addr->sin, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + if (ogs_gtp_self()->gtpc_addr6) { + ret = fd_msg_avp_new(ogs_diam_gy_ggsn_address, 0, &avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_value_encode(&ogs_gtp_self()->gtpc_addr->sin6, avpch2); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + + /* Called-Station-Id */ + ret = fd_msg_avp_new(ogs_diam_gy_called_station_id, 0, &avpch2); + ogs_assert(ret == 0); + ogs_assert(sess->session.name); + val.os.data = (uint8_t*)sess->session.name; + val.os.len = strlen(sess->session.name); + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + /* 3GPP-SGSN-MCC-MNC */ + ret = fd_msg_avp_new(ogs_diam_gy_3gpp_sgsn_mcc_mnc, 0, &avpch2); + ogs_assert(ret == 0); + val.os.data = (uint8_t *)ogs_plmn_id_to_string(&sess->plmn_id, buf); + val.os.len = strlen(buf); + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + /* 3GPP-MS-Timezone */ + if (sess->gtp.ue_timezone.presence && + sess->gtp.ue_timezone.len && sess->gtp.ue_timezone.data) { + ret = fd_msg_avp_new(ogs_diam_gy_3gpp_ms_timezone, 0, &avpch2); + ogs_assert(ret == 0); + val.os.data = sess->gtp.ue_timezone.data; + val.os.len = sess->gtp.ue_timezone.len; + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + + /* 3GPP-User-Location-Info */ + if (sess->gtp.user_location_information.presence) { + ogs_gtp2_uli_t uli; + int16_t uli_len; + + uint8_t uli_buf[OGS_GTP2_MAX_ULI_LEN]; + + uli_len = ogs_gtp2_parse_uli( + &uli, &sess->gtp.user_location_information); + ogs_assert(sess->gtp.user_location_information.len == uli_len); + + ogs_assert(sess->gtp.user_location_information.data); + ogs_assert(sess->gtp.user_location_information.len); + memcpy(&uli_buf, sess->gtp.user_location_information.data, + sess->gtp.user_location_information.len); + + /* Update Gy ULI Type */ + if (uli.flags.tai && uli.flags.e_cgi) + uli_buf[0] = + OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI; + else if (uli.flags.tai) + uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI; + else if (uli.flags.e_cgi) + uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI; + + if (uli_buf[0]) { + ret = fd_msg_avp_new( + ogs_diam_gy_3gpp_user_location_info, 0, &avpch2); + ogs_assert(ret == 0); + val.os.data = (uint8_t *)&uli_buf; + val.os.len = sess->gtp.user_location_information.len; + ret = fd_msg_avp_setvalue(avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + } + } + + /* PS-Information AVP add to req: */ + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + /* Service-Information AVP add to req: */ + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); +} + /* 3GPP TS 32.299 6.4.2 Credit-Control-Request message */ void smf_gy_send_ccr(smf_sess_t *sess, void *xact, uint32_t cc_request_type) @@ -258,7 +457,6 @@ void smf_gy_send_ccr(smf_sess_t *sess, void *xact, struct sess_state *sess_data = NULL, *svg; struct session *session = NULL; int new; - char buf[OGS_PLMNIDSTRLEN]; const char *service_context_id = "open5gs-smfd@open5gs.org"; uint32_t timestamp; @@ -550,77 +748,8 @@ void smf_gy_send_ccr(smf_sess_t *sess, void *xact, /* OC-Supported-Features */ - /* 3GPP-User-Location-Info */ - if (sess->gtp.user_location_information.presence) { - ogs_gtp2_uli_t uli; - int16_t uli_len; - - uint8_t uli_buf[OGS_GTP2_MAX_ULI_LEN]; - - uli_len = ogs_gtp2_parse_uli( - &uli, &sess->gtp.user_location_information); - ogs_assert(sess->gtp.user_location_information.len == uli_len); - - ogs_assert(sess->gtp.user_location_information.data); - ogs_assert(sess->gtp.user_location_information.len); - memcpy(&uli_buf, sess->gtp.user_location_information.data, - sess->gtp.user_location_information.len); - - /* Update Gy ULI Type */ - if (uli.flags.tai && uli.flags.e_cgi) - uli_buf[0] = - OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI; - else if (uli.flags.tai) - uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI; - else if (uli.flags.e_cgi) - uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI; - - if (uli_buf[0]) { - ret = fd_msg_avp_new( - ogs_diam_gy_3gpp_user_location_info, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)&uli_buf; - val.os.len = sess->gtp.user_location_information.len; - 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); - } - } - - /* 3GPP-MS-Timezone */ - if (sess->gtp.ue_timezone.presence && - sess->gtp.ue_timezone.len && sess->gtp.ue_timezone.data) { - ret = fd_msg_avp_new(ogs_diam_gy_3gpp_ms_timezone, 0, &avp); - ogs_assert(ret == 0); - val.os.data = sess->gtp.ue_timezone.data; - val.os.len = sess->gtp.ue_timezone.len; - 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); - } - - /* 3GPP-SGSN-MCC-MNC */ - ret = fd_msg_avp_new(ogs_diam_gy_3gpp_sgsn_mcc_mnc, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)ogs_plmn_id_to_string(&sess->plmn_id, buf); - val.os.len = strlen(buf); - 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); - - /* Called-Station-Id */ - ret = fd_msg_avp_new(ogs_diam_gy_called_station_id, 0, &avp); - ogs_assert(ret == 0); - ogs_assert(sess->session.name); - val.os.data = (uint8_t*)sess->session.name; - val.os.len = strlen(sess->session.name); - 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); + /* Service-Information */ + fill_service_information_ccr(sess, cc_request_type, req); ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts);