diff --git a/docs/_docs/guide/01-quickstart.md b/docs/_docs/guide/01-quickstart.md index e745dab39..fa11e1eb9 100644 --- a/docs/_docs/guide/01-quickstart.md +++ b/docs/_docs/guide/01-quickstart.md @@ -233,7 +233,7 @@ MME-frDi = 127.0.0.2 :3868 for S6a SGWC-gtpc = 127.0.0.3 :2123 for S11 SGWC-pfcp = 127.0.0.3 :8805 for Sxa -SMF-gtpc = 127.0.0.4 :2123 for S5c, N11 +SMF-gtpc = 127.0.0.4 :2123 for S5c SMF-gtpu = 127.0.0.4 :2152 for N4u (Sxu) SMF-pfcp = 127.0.0.4 :8805 for N4 (Sxb) SMF-frDi = 127.0.0.4 :3868 for Gx auth diff --git a/lib/gtp/util.c b/lib/gtp/util.c index 1e59239d2..f0defe73c 100644 --- a/lib/gtp/util.c +++ b/lib/gtp/util.c @@ -180,3 +180,68 @@ uint16_t ogs_in_cksum(uint16_t *addr, int len) return answer; } + +void ogs_gtp2_sender_f_teid( + ogs_gtp2_sender_f_teid_t *sender_f_teid, ogs_gtp2_message_t *message) +{ + ogs_gtp2_tlv_f_teid_t *tlv_f_teid = NULL; + ogs_gtp2_f_teid_t *f_teid = NULL; + + ogs_assert(sender_f_teid); + ogs_assert(message); + + memset(sender_f_teid, 0, sizeof(*sender_f_teid)); + + switch (message->h.type) { + case OGS_GTP2_CREATE_SESSION_REQUEST_TYPE: + tlv_f_teid = &message->create_session_request. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: + tlv_f_teid = &message->create_session_response. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: + tlv_f_teid = &message->modify_bearer_request. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: + tlv_f_teid = &message->delete_session_request. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_MODIFY_BEARER_COMMAND_TYPE: + tlv_f_teid = &message->modify_bearer_command. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_DELETE_BEARER_COMMAND_TYPE: + tlv_f_teid = &message->delete_bearer_command. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: + tlv_f_teid = &message->bearer_resource_command. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: + tlv_f_teid = &message->create_indirect_data_forwarding_tunnel_request. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: + tlv_f_teid = &message->create_indirect_data_forwarding_tunnel_response. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: + tlv_f_teid = &message->downlink_data_notification. + sender_f_teid_for_control_plane; + break; + case OGS_GTP2_MODIFY_ACCESS_BEARERS_REQUEST_TYPE: + tlv_f_teid = &message->modify_access_bearers_request. + sender_f_teid_for_control_plane; + default: + break; + } + + if (tlv_f_teid && tlv_f_teid->presence && (f_teid = tlv_f_teid->data)) { + sender_f_teid->teid_presence = true; + sender_f_teid->teid = be32toh(f_teid->teid); + } +} diff --git a/lib/gtp/util.h b/lib/gtp/util.h index 7fabdd7c6..69339f0e8 100644 --- a/lib/gtp/util.h +++ b/lib/gtp/util.h @@ -32,6 +32,14 @@ int ogs_gtpu_parse_header( ogs_gtp2_header_desc_t *header_desc, ogs_pkbuf_t *pkbuf); uint16_t ogs_in_cksum(uint16_t *addr, int len); +typedef struct ogs_gtp2_sender_f_teid_s { + bool teid_presence; + uint32_t teid; +} ogs_gtp2_sender_f_teid_t; + +void ogs_gtp2_sender_f_teid( + ogs_gtp2_sender_f_teid_t *sender_f_teid, ogs_gtp2_message_t *message); + #ifdef __cplusplus } #endif diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index da65704e7..46c4fb0ba 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -281,7 +281,8 @@ uint8_t smf_s5c_handle_create_session_request( /* Control Plane(DL) : SGW-S5C */ sgw_s5c_teid = req->sender_f_teid_for_control_plane.data; ogs_assert(sgw_s5c_teid); - sess->sgw_s5c_teid = be32toh(sgw_s5c_teid->teid); + /* sess->sgw_s5c_teid has already been updated in SMF-SM */ + ogs_assert(sess->sgw_s5c_teid == be32toh(sgw_s5c_teid->teid)); rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip); ogs_assert(rv == OGS_OK); @@ -479,7 +480,8 @@ uint8_t smf_s5c_handle_delete_session_request( void smf_s5c_handle_modify_bearer_request( smf_sess_t *sess, ogs_gtp_xact_t *gtp_xact, - ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req) + ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req, + ogs_gtp2_sender_f_teid_t *sender_f_teid) { int rv, i; uint8_t cause_value = 0; @@ -492,6 +494,7 @@ void smf_s5c_handle_modify_bearer_request( ogs_assert(gtp_xact); ogs_assert(req); + ogs_assert(sender_f_teid); /************************ * Check Session Context @@ -504,7 +507,10 @@ void smf_s5c_handle_modify_bearer_request( } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, + ogs_gtp2_send_error_message(gtp_xact, + sess ? sess->sgw_s5c_teid : + sender_f_teid->teid_presence == true ? + sender_f_teid->teid : 0, OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); return; } @@ -1132,7 +1138,8 @@ static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp2_tft_t *tft, int i) void smf_s5c_handle_bearer_resource_command( smf_sess_t *sess, ogs_gtp_xact_t *xact, - ogs_gtp2_bearer_resource_command_t *cmd) + ogs_gtp2_bearer_resource_command_t *cmd, + ogs_gtp2_sender_f_teid_t *sender_f_teid) { int rv; uint8_t cause_value = 0; @@ -1153,6 +1160,7 @@ void smf_s5c_handle_bearer_resource_command( ogs_assert(xact); ogs_assert(cmd); + ogs_assert(sender_f_teid); ogs_debug("Bearer Resource Command"); @@ -1186,7 +1194,10 @@ void smf_s5c_handle_bearer_resource_command( } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, + ogs_gtp2_send_error_message(xact, + sess ? sess->sgw_s5c_teid : + sender_f_teid->teid_presence == true ? + sender_f_teid->teid : 0, OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value); return; } diff --git a/src/smf/s5c-handler.h b/src/smf/s5c-handler.h index 0312c5077..a8addb576 100644 --- a/src/smf/s5c-handler.h +++ b/src/smf/s5c-handler.h @@ -39,7 +39,8 @@ uint8_t smf_s5c_handle_delete_session_request( ogs_gtp2_delete_session_request_t *req); void smf_s5c_handle_modify_bearer_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, - ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req); + ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req, + ogs_gtp2_sender_f_teid_t *sender_f_teid); void smf_s5c_handle_create_bearer_response( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_create_bearer_response_t *rsp); @@ -51,7 +52,8 @@ bool smf_s5c_handle_delete_bearer_response( ogs_gtp2_delete_bearer_response_t *rsp); void smf_s5c_handle_bearer_resource_command( smf_sess_t *sess, ogs_gtp_xact_t *xact, - ogs_gtp2_bearer_resource_command_t *cmd); + ogs_gtp2_bearer_resource_command_t *cmd, + ogs_gtp2_sender_f_teid_t *sender_f_teid); #ifdef __cplusplus } diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 1ba9e4319..40715ea97 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -58,6 +58,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_gtp_xact_t *gtp_xact = NULL; ogs_gtp2_message_t gtp2_message; + ogs_gtp2_sender_f_teid_t gtp2_sender_f_teid; ogs_gtp1_message_t gtp1_message; ogs_diam_gx_message_t *gx_message = NULL; @@ -108,6 +109,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) } e->gtp2_message = >p2_message; + ogs_gtp2_sender_f_teid(>p2_sender_f_teid, >p2_message); + rv = ogs_gtp_xact_receive(smf_gnode->gnode, >p2_message.h, >p_xact); if (rv != OGS_OK) { ogs_pkbuf_free(recvbuf); @@ -144,11 +147,21 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) } if (!sess) { ogs_error("No Session"); - ogs_gtp2_send_error_message(gtp_xact, 0, + ogs_gtp2_send_error_message(gtp_xact, + gtp2_sender_f_teid.teid_presence == true ? + gtp2_sender_f_teid.teid : 0, OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); break; } + + if (gtp2_sender_f_teid.teid_presence == true) + sess->sgw_s5c_teid = gtp2_sender_f_teid.teid; + + ogs_debug(" SGW_S5C_TEID[0x%x], Sender F-TEID(%d)[0x%x]", + sess->sgw_s5c_teid, + gtp2_sender_f_teid.teid_presence, gtp2_sender_f_teid.teid); + e->sess = sess; ogs_fsm_dispatch(&sess->sm, e); break; @@ -158,18 +171,33 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) smf_metrics_inst_gtp_node_inc(smf_gnode->metrics, SMF_METR_GTP_NODE_CTR_S5C_RX_DELETESESSIONREQ); if (!sess) { ogs_error("No Session"); - ogs_gtp2_send_error_message(gtp_xact, 0, + ogs_gtp2_send_error_message(gtp_xact, + gtp2_sender_f_teid.teid_presence == true ? + gtp2_sender_f_teid.teid : 0, OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); break; } + if (gtp2_sender_f_teid.teid_presence == true) { + if (sess->sgw_s5c_teid != gtp2_sender_f_teid.teid) { + ogs_error("Invalid Sender F-TEID [0x%x != 0x%x]", + sess->sgw_s5c_teid, gtp2_sender_f_teid.teid); + ogs_gtp2_send_error_message(gtp_xact, + gtp2_sender_f_teid.teid_presence == true ? + gtp2_sender_f_teid.teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, + OGS_GTP2_CAUSE_INVALID_MESSAGE_FORMAT); + break; + } + } e->sess = sess; ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); smf_s5c_handle_modify_bearer_request( - sess, gtp_xact, recvbuf, >p2_message.modify_bearer_request); + sess, gtp_xact, recvbuf, + >p2_message.modify_bearer_request, >p2_sender_f_teid); break; case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); @@ -194,7 +222,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: if (!gtp2_message.h.teid_presence) ogs_error("No TEID"); smf_s5c_handle_bearer_resource_command( - sess, gtp_xact, >p2_message.bearer_resource_command); + sess, gtp_xact, + >p2_message.bearer_resource_command, >p2_sender_f_teid); break; default: ogs_warn("Not implemented(type:%d)", gtp2_message.h.type);