/* * Copyright (C) 2019,2020 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 "s2b-handler.h" #include "gtp-path.h" void test_s2b_handle_create_session_response( ogs_gtp_xact_t *xact, test_sess_t *sess, ogs_gtp2_create_session_response_t *rsp) { int rv, i; uint8_t cause_value; test_bearer_t *bearer = NULL; ogs_gtp2_f_teid_t *smf_s2b_c_teid = NULL; ogs_gtp2_f_teid_t *smf_s2b_u_teid = NULL; ogs_paa_t paa; ogs_assert(xact); ogs_assert(sess); ogs_assert(rsp); rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); if (rsp->cause.presence) { ogs_gtp2_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { } else if (cause_value == OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE) { } else { ogs_error("GTP Failed [CAUSE:%d]", cause_value); return; } } else { ogs_error("No Cause"); return; } if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) { ogs_error("No S5/S8 TEID"); return; } if (rsp->pdn_address_allocation.presence == 0) { ogs_error("No PDN Address Allocation"); return; } ogs_expect( rsp->pdn_address_allocation.data && rsp->pdn_address_allocation.len); for (i = 0; i < OGS_BEARER_PER_UE; i++) { if (rsp->bearer_contexts_created[i].presence == 0) { break; } if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) { ogs_error("No EBI"); break; } if (rsp->bearer_contexts_created[i].s12_rnc_f_teid.presence == 0) { ogs_error("No S1U TEID"); break; } bearer = test_bearer_find_by_sess_ebi( sess, rsp->bearer_contexts_created[i].eps_bearer_id.u8); ogs_assert(bearer); smf_s2b_u_teid = rsp->bearer_contexts_created[i].s12_rnc_f_teid.data; ogs_assert(smf_s2b_u_teid); bearer->sgw_s1u_teid = be32toh(smf_s2b_u_teid->teid); ogs_assert(OGS_OK == ogs_gtp2_f_teid_to_ip(smf_s2b_u_teid, &bearer->sgw_s1u_ip)); } smf_s2b_c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; ogs_assert(smf_s2b_c_teid); sess->smf_s2b_c_teid = be32toh(smf_s2b_c_teid->teid); memcpy(&paa, rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len); switch (paa.session_type) { case OGS_PDU_SESSION_TYPE_IPV4: sess->ue_ip.ipv4 = 1; sess->ue_ip.addr = paa.addr; break; case OGS_PDU_SESSION_TYPE_IPV6: sess->ue_ip.ipv6 = 1; memset(sess->ue_ip.addr6, 0, 8); memcpy(sess->ue_ip.addr6+8, paa.addr6, 8); break; case OGS_PDU_SESSION_TYPE_IPV4V6: sess->ue_ip.ipv4 = 1; sess->ue_ip.addr = paa.both.addr; sess->ue_ip.ipv6 = 1; memset(sess->ue_ip.addr6, 0, 8); memcpy(sess->ue_ip.addr6+8, paa.both.addr6, 8); break; default: ogs_fatal("Invalid PDU Address Type [%d]", paa.session_type); ogs_assert_if_reached(); } } void test_s2b_handle_delete_session_response( ogs_gtp_xact_t *xact, test_sess_t *sess, ogs_gtp2_delete_session_response_t *rsp) { int rv; uint8_t cause_value; ogs_assert(xact); ogs_assert(sess); ogs_assert(rsp); cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); if (rsp->cause.presence) { ogs_gtp2_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); } test_sess_remove(sess); } void test_s2b_handle_create_bearer_request( ogs_gtp_xact_t *xact, test_sess_t *sess, ogs_gtp2_create_bearer_request_t *req) { int rv; test_bearer_t *linked_bearer = NULL; test_bearer_t *bearer = NULL; ogs_gtp2_f_teid_t *smf_s2b_u_teid = NULL; ogs_assert(xact); ogs_assert(sess); ogs_assert(req); if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No Linked EBI"); return; } if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); return; } if (req->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); return; } if (req->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) { ogs_error("No GTP TEID"); return; } if (req->bearer_contexts.bearer_level_qos.presence == 0) { ogs_error("No QoS"); return; } if (req->bearer_contexts.tft.presence == 0) { ogs_error("No TFT"); return; } linked_bearer = test_bearer_find_by_sess_ebi(sess, req->linked_eps_bearer_id.u8); ogs_assert(linked_bearer); ogs_assert(linked_bearer->sess == sess); bearer = test_bearer_add(sess, linked_bearer->ebi + ogs_list_count(&sess->bearer_list)); ogs_assert(bearer); /* Receive Data Plane(UL) : SMF-S2B-U */ smf_s2b_u_teid = req->bearer_contexts.s4_u_sgsn_f_teid.data; ogs_assert(smf_s2b_u_teid); bearer->sgw_s1u_teid = be32toh(smf_s2b_u_teid->teid); rv = ogs_gtp2_f_teid_to_ip(smf_s2b_u_teid, &bearer->sgw_s1u_ip); ogs_assert(rv == OGS_OK); ogs_assert(OGS_OK == test_s2b_send_create_bearer_response(bearer, xact)); } void test_s2b_handle_delete_bearer_request( ogs_gtp_xact_t *xact, test_sess_t *sess, ogs_gtp2_delete_bearer_request_t *req) { test_bearer_t *bearer = NULL; ogs_gtp2_cause_t *cause = NULL; ogs_assert(xact); ogs_assert(sess); ogs_assert(req); ogs_assert(req->cause.presence); cause = req->cause.data; ogs_assert(cause); ogs_assert(cause->value == OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP); ogs_assert(req->linked_eps_bearer_id.presence); bearer = test_bearer_find_by_sess_ebi(sess, req->linked_eps_bearer_id.u8); ogs_assert(bearer); ogs_assert(OGS_OK == test_s2b_send_delete_bearer_response(bearer, xact)); test_sess_remove(sess); }